]> git.ipfire.org Git - thirdparty/squid.git/blame - tools/squidclient/gssapi_support.cc
SourceFormat Enforcement
[thirdparty/squid.git] / tools / squidclient / gssapi_support.cc
CommitLineData
5f623035 1/*
bde978a6 2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
5f623035
AJ
3 *
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.
7 */
8
b2050d4d 9#include "squid.h"
abbb1186
AJ
10
11#if HAVE_GSSAPI
12
b2050d4d
AJ
13#include "base64.h"
14#include "tools/squidclient/gssapi_support.h"
15
abbb1186 16#include <iostream>
b2050d4d
AJ
17
18#if !defined(gss_mech_spnego)
19static gss_OID_desc _gss_mech_spnego = {6, (void *) "\x2b\x06\x01\x05\x05\x02"};
20gss_OID gss_mech_spnego = &_gss_mech_spnego;
21#endif
22
23#define BUFFER_SIZE 8192
24
25/**
26 * Check return valuse major_status, minor_status for error and print error description
27 * in case of an error.
28 *
29 * \retval true in case of gssapi error
30 * \retval false in case of no gssapi error
31 */
32bool
33check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char *function)
34{
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];
40 size_t len;
41
42 len = 0;
43 msg_ctx = 0;
44 while (!msg_ctx) {
45 /* convert major status code (GSS-API error) to text */
46 maj_stat = gss_display_status(&min_stat, major_status,
47 GSS_C_GSS_CODE,
48 GSS_C_NULL_OID,
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);
54 break;
55 }
56 gss_release_buffer(&min_stat, &status_string);
57 }
58 snprintf(buf + len, BUFFER_SIZE-len, "%s", ". ");
59 len += 2;
60 msg_ctx = 0;
61 while (!msg_ctx) {
62 /* convert minor status code (underlying routine error) to text */
63 maj_stat = gss_display_status(&min_stat, minor_status,
64 GSS_C_MECH_CODE,
65 GSS_C_NULL_OID,
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);
71 break;
72 }
73 gss_release_buffer(&min_stat, &status_string);
74 }
75 std::cerr << "ERROR: " << function << " failed: " << buf << std::endl;
76 return true;
77 }
78 return false;
79}
80
81/**
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
85 *
86 * \return base64 encoded token if successful,
87 * string "ERROR" if unsuccessful
88 */
89char *
90GSSAPI_token(const char *server)
91{
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;
98 char *token = NULL;
99
100 setbuf(stdout, NULL);
101 setbuf(stdin, NULL);
102
103 if (!server) {
104 std::cerr << "ERROR: GSSAPI: No server name" << std::endl;
aadbbd7d
AJ
105 token = new char[6];
106 memcpy(token, "ERROR", 5);
107 token[5] = '\0';
108 return token;
b2050d4d
AJ
109 }
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);
113
114 major_status = gss_import_name(&minor_status, &service,
115 gss_nt_service_name, &server_name);
116
117 if (!check_gss_err(major_status, minor_status, "gss_import_name()")) {
118
119 major_status = gss_init_sec_context(&minor_status,
120 GSS_C_NO_CREDENTIAL,
121 &gss_context,
122 server_name,
123 gss_mech_spnego,
124 0,
125 0,
126 GSS_C_NO_CHANNEL_BINDINGS,
127 &input_token,
128 NULL,
129 &output_token,
130 NULL,
131 NULL);
132
aadbbd7d
AJ
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);
139 b64buf[blen] = '\0';
b2050d4d 140
aadbbd7d 141 token = reinterpret_cast<char*>(b64buf);
b2050d4d
AJ
142 }
143 }
144
aadbbd7d
AJ
145 if (!output_token.length) {
146 token = new char[6];
147 memcpy(token, "ERROR", 5);
148 token[5] = '\0';
149 }
150
b2050d4d
AJ
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);
156
157 return token;
158}
159
160#endif /* HAVE_GSSAPI */
f53969cc 161