2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
14 #include "tools/squidclient/gssapi_support.h"
18 #if !defined(gss_mech_spnego)
19 static gss_OID_desc _gss_mech_spnego
= {6, (void *) "\x2b\x06\x01\x05\x05\x02"};
20 gss_OID gss_mech_spnego
= &_gss_mech_spnego
;
23 #define BUFFER_SIZE 8192
26 * Check return valuse major_status, minor_status for error and print error description
27 * in case of an error.
29 * \retval true in case of gssapi error
30 * \retval false in case of no gssapi error
33 check_gss_err(OM_uint32 major_status
, OM_uint32 minor_status
, const char *function
)
35 if (GSS_ERROR(major_status
)) {
36 OM_uint32 maj_stat
, min_stat
;
37 OM_uint32 msg_ctx
= 0;
38 gss_buffer_desc status_string
;
39 char buf
[BUFFER_SIZE
];
45 /* convert major status code (GSS-API error) to text */
46 maj_stat
= gss_display_status(&min_stat
, major_status
,
49 &msg_ctx
, &status_string
);
50 if (maj_stat
== GSS_S_COMPLETE
) {
51 snprintf(buf
+ len
, BUFFER_SIZE
-len
, "%s", (char *) status_string
.value
);
52 len
+= status_string
.length
;
53 gss_release_buffer(&min_stat
, &status_string
);
56 gss_release_buffer(&min_stat
, &status_string
);
58 snprintf(buf
+ len
, BUFFER_SIZE
-len
, "%s", ". ");
62 /* convert minor status code (underlying routine error) to text */
63 maj_stat
= gss_display_status(&min_stat
, minor_status
,
66 &msg_ctx
, &status_string
);
67 if (maj_stat
== GSS_S_COMPLETE
) {
68 snprintf(buf
+ len
, BUFFER_SIZE
-len
,"%s", (char *) status_string
.value
);
69 len
+= status_string
.length
;
70 gss_release_buffer(&min_stat
, &status_string
);
73 gss_release_buffer(&min_stat
, &status_string
);
75 std::cerr
<< "ERROR: " << function
<< " failed: " << buf
<< std::endl
;
82 * Get gssapi token for service HTTP/<server>
83 * User has to initiate a kinit user@DOMAIN on commandline first for the
84 * function to be successful
86 * \return base64 encoded token if successful,
87 * string "ERROR" if unsuccessful
90 GSSAPI_token(const char *server
)
92 OM_uint32 major_status
, minor_status
;
93 gss_ctx_id_t gss_context
= GSS_C_NO_CONTEXT
;
94 gss_name_t server_name
= GSS_C_NO_NAME
;
95 gss_buffer_desc service
= GSS_C_EMPTY_BUFFER
;
96 gss_buffer_desc input_token
= GSS_C_EMPTY_BUFFER
;
97 gss_buffer_desc output_token
= GSS_C_EMPTY_BUFFER
;
100 setbuf(stdout
, NULL
);
104 std::cerr
<< "ERROR: GSSAPI: No server name" << std::endl
;
106 memcpy(token
, "ERROR", 5);
110 service
.value
= xmalloc(strlen("HTTP") + strlen(server
) + 2);
111 snprintf((char *) service
.value
, strlen("HTTP") + strlen(server
) + 2, "%s@%s", "HTTP", server
);
112 service
.length
= strlen((char *) service
.value
);
114 major_status
= gss_import_name(&minor_status
, &service
,
115 gss_nt_service_name
, &server_name
);
117 if (!check_gss_err(major_status
, minor_status
, "gss_import_name()")) {
119 major_status
= gss_init_sec_context(&minor_status
,
126 GSS_C_NO_CHANNEL_BINDINGS
,
133 if (!check_gss_err(major_status
, minor_status
, "gss_init_sec_context()") && output_token
.length
) {
134 uint8_t *b64buf
= new uint8_t[base64_encode_len(output_token
.length
)];
135 struct base64_encode_ctx ctx
;
136 base64_encode_init(&ctx
);
137 size_t blen
= base64_encode_update(&ctx
, b64buf
, output_token
.length
, reinterpret_cast<const uint8_t*>(output_token
.value
));
138 blen
+= base64_encode_final(&ctx
, b64buf
+blen
);
141 token
= reinterpret_cast<char*>(b64buf
);
145 if (!output_token
.length
) {
147 memcpy(token
, "ERROR", 5);
151 gss_delete_sec_context(&minor_status
, &gss_context
, NULL
);
152 gss_release_buffer(&minor_status
, &service
);
153 gss_release_buffer(&minor_status
, &input_token
);
154 gss_release_buffer(&minor_status
, &output_token
);
155 gss_release_name(&minor_status
, &server_name
);
160 #endif /* HAVE_GSSAPI */