Squid Web Cache master
Loading...
Searching...
No Matches
negotiate_kerberos_auth_test.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
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
9/*
10 * -----------------------------------------------------------------------------
11 *
12 * Author: Markus Moeller (markus_moeller at compuserve.com)
13 *
14 * Copyright (C) 2007 Markus Moeller. All rights reserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
29 *
30 * -----------------------------------------------------------------------------
31 */
32
33#include "squid.h"
34
35#if HAVE_GSSAPI
36#include <cerrno>
37#include <cstring>
38#include <ctime>
39#if HAVE_NETDB_H
40#include <netdb.h>
41#endif
42#if HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45
46#include "base64.h"
47#include "util.h"
48
49#if HAVE_GSS_H
50#include <gss.h>
51#endif
52
53#if USE_APPLE_KRB5
54#define GSSKRB_APPLE_DEPRECATED(x)
55#endif
56#if HAVE_GSSAPI_GSSAPI_H
57#include <gssapi/gssapi.h>
58#elif HAVE_GSSAPI_H
59#include <gssapi.h>
60#endif
61#if HAVE_GSSAPI_GSSAPI_KRB5_H
62#include <gssapi/gssapi_krb5.h>
63#endif
64#if HAVE_GSSAPI_GSSAPI_GENERIC_H
65#include <gssapi/gssapi_generic.h>
66#endif
67#if HAVE_GSSAPI_GSSAPI_EXT_H
68#include <gssapi/gssapi_ext.h>
69#endif
70
71#ifndef gss_nt_service_name
72#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
73#endif
74
75static const char *LogTime(void);
76
77int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
78 const char *function);
79
80const char *squid_kerb_proxy_auth(char *proxy);
81
82#define PROGRAM "negotiate_kerberos_auth_test"
83
84static const char *
85LogTime()
86{
87 struct tm *tm;
88 struct timeval now;
89 static time_t last_t = 0;
90 static char buf[128];
91
92 gettimeofday(&now, nullptr);
93 if (now.tv_sec != last_t) {
94 tm = localtime((const time_t *) &now.tv_sec);
95 strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
96 last_t = now.tv_sec;
97 }
98 return buf;
99}
100
101#ifndef gss_mech_spnego
102static gss_OID_desc _gss_mech_spnego = {6, (void *) "\x2b\x06\x01\x05\x05\x02"};
103gss_OID gss_mech_spnego = &_gss_mech_spnego;
104#endif
105
106int
107check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
108 const char *function)
109{
110 if (GSS_ERROR(major_status)) {
111 OM_uint32 maj_stat, min_stat;
112 OM_uint32 msg_ctx = 0;
113 gss_buffer_desc status_string;
114 char buf[1024];
115 size_t len;
116
117 len = 0;
118 msg_ctx = 0;
119 do {
120 /* convert major status code (GSS-API error) to text */
121 maj_stat = gss_display_status(&min_stat, major_status,
122 GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string);
123 if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) {
124 if (sizeof(buf) > len + status_string.length + 1) {
125 snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
126 len += status_string.length;
127 }
128 } else
129 msg_ctx = 0;
130 gss_release_buffer(&min_stat, &status_string);
131 } while (msg_ctx);
132 if (sizeof(buf) > len + 2) {
133 snprintf(buf + len, (sizeof(buf) - len), "%s", ". ");
134 len += 2;
135 }
136 msg_ctx = 0;
137 do {
138 /* convert minor status code (underlying routine error) to text */
139 maj_stat = gss_display_status(&min_stat, minor_status,
140 GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string);
141 if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) {
142 if (sizeof(buf) > len + status_string.length) {
143 snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value);
144 len += status_string.length;
145 }
146 } else
147 msg_ctx = 0;
148 gss_release_buffer(&min_stat, &status_string);
149 } while (msg_ctx);
150 fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function,
151 buf);
152 return (1);
153 }
154 return (0);
155}
156
157const char *
158squid_kerb_proxy_auth(char *proxy)
159{
160 OM_uint32 major_status, minor_status;
161 gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
162 gss_name_t server_name = GSS_C_NO_NAME;
163 gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
164 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
165 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
166 char *token = nullptr;
167
168 setbuf(stdout, nullptr);
169 setbuf(stdin, nullptr);
170
171 if (!proxy) {
172 fprintf(stderr, "%s| %s: Error: No proxy server name\n", LogTime(),
173 PROGRAM);
174 return nullptr;
175 }
176 service.value = xmalloc(strlen("HTTP") + strlen(proxy) + 2);
177 snprintf((char *) service.value, strlen("HTTP") + strlen(proxy) + 2, "%s@%s", "HTTP", proxy);
178 service.length = strlen((char *) service.value);
179
180 major_status = gss_import_name(&minor_status, &service,
181 gss_nt_service_name, &server_name);
182
183 if (!check_gss_err(major_status, minor_status, "gss_import_name()")) {
184
185 major_status = gss_init_sec_context(&minor_status,
186 GSS_C_NO_CREDENTIAL, &gss_context, server_name,
187 gss_mech_spnego,
188 0,
189 0,
190 GSS_C_NO_CHANNEL_BINDINGS,
191 &input_token, nullptr, &output_token, nullptr, nullptr);
192
193 if (!check_gss_err(major_status, minor_status, "gss_init_sec_context()") && output_token.length) {
194 token = (char *) xcalloc(base64_encode_len(output_token.length), 1);
195 struct base64_encode_ctx ctx;
196 base64_encode_init(&ctx);
197 size_t blen = base64_encode_update(&ctx, token, output_token.length, reinterpret_cast<const uint8_t*>(output_token.value));
198 blen += base64_encode_final(&ctx, token+blen);
199 }
200 }
201
202 gss_delete_sec_context(&minor_status, &gss_context, nullptr);
203 gss_release_buffer(&minor_status, &service);
204 gss_release_buffer(&minor_status, &input_token);
205 gss_release_buffer(&minor_status, &output_token);
206 gss_release_name(&minor_status, &server_name);
207
208 return token;
209}
210
211int
212main(int argc, char *argv[])
213{
214 const char *Token;
215 int count;
216
217 if (argc < 2) {
218 fprintf(stderr, "%s| %s: Error: No proxy server name given\n",
219 LogTime(), PROGRAM);
220 return 99;
221 }
222 if (argc == 3) {
223 count = atoi(argv[2]);
224 while (count > 0) {
225 Token = (const char *) squid_kerb_proxy_auth(argv[1]);
226 fprintf(stdout, "YR %s\n", Token ? Token : "NULL");
227 --count;
228 }
229 fprintf(stdout, "QQ\n");
230 } else {
231 Token = (const char *) squid_kerb_proxy_auth(argv[1]);
232 fprintf(stdout, "Token: %s\n", Token ? Token : "NULL");
233 }
234
235 return EXIT_SUCCESS;
236}
237
238#else
239#include <cstdlib>
240int
241main(int argc, char *argv[])
242{
243 return -1;
244}
245
246#endif /* HAVE_GSSAPI */
247
#define PROGRAM
Definition support.h:169
const char * LogTime(void)
void base64_encode_init(struct base64_encode_ctx *ctx)
Definition base64.c:232
size_t base64_encode_update(struct base64_encode_ctx *ctx, char *dst, size_t length, const uint8_t *src)
Definition base64.c:265
size_t base64_encode_final(struct base64_encode_ctx *ctx, char *dst)
Definition base64.c:308
#define base64_encode_len(length)
Definition base64.h:169
int main()
#define gss_nt_service_name
int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char *function, int log, int sout)
#define xmalloc
void * xcalloc(size_t n, size_t sz)
Definition xalloc.cc:71