negotiate_kerberos_auth_test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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 
75 static const char *LogTime(void);
76 
77 int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
78  const char *function);
79 
80 const char *squid_kerb_proxy_auth(char *proxy);
81 
82 #define PROGRAM "negotiate_kerberos_auth_test"
83 
84 static const char *
85 LogTime()
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
102 static gss_OID_desc _gss_mech_spnego = {6, (void *) "\x2b\x06\x01\x05\x05\x02"};
103 gss_OID gss_mech_spnego = &_gss_mech_spnego;
104 #endif
105 
106 int
107 check_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 
157 const char *
158 squid_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 
211 int
212 main(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>
240 int
241 main(int argc, char *argv[])
242 {
243  return -1;
244 }
245 
246 #endif /* HAVE_GSSAPI */
247 
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
#define base64_encode_len(length)
Definition: base64.h:169
#define xmalloc
#define gss_nt_service_name
#define PROGRAM
Definition: support.h:169
int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char *function, int log, int sout)
size_t base64_encode_final(struct base64_encode_ctx *ctx, char *dst)
Definition: base64.c:308
int main(int argc, char *argv[])
void base64_encode_init(struct base64_encode_ctx *ctx)
Definition: base64.c:232
const char * LogTime(void)
size_t base64_encode_update(struct base64_encode_ctx *ctx, char *dst, size_t length, const uint8_t *src)
Definition: base64.c:265

 

Introduction

Documentation

Support

Miscellaneous