/*
- * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
struct _krb5_kt_list *next;
krb5_keytab_entry *entry;
} *krb5_kt_list;
-krb5_kt_list ktlist = NULL;
+krb5_kt_list ktlist = nullptr;
+
+krb5_keytab memory_keytab;
krb5_error_code krb5_free_kt_list(krb5_context context, krb5_kt_list kt_list);
krb5_error_code krb5_write_keytab(krb5_context context,
* char hostname[sysconf(_SC_HOST_NAME_MAX)];
*/
char hostname[1024];
- struct addrinfo *hres = NULL, *hres_list;
+ struct addrinfo *hres = nullptr, *hres_list;
int rc, count;
rc = gethostname(hostname, sizeof(hostname)-1);
debug((char *) "%s| %s: ERROR: resolving hostname '%s' failed\n", LogTime(), PROGRAM, hostname);
fprintf(stderr, "%s| %s: ERROR: resolving hostname '%s' failed\n",
LogTime(), PROGRAM, hostname);
- return NULL;
+ return nullptr;
}
- rc = getaddrinfo(hostname, NULL, NULL, &hres);
- if (rc != 0 || hres == NULL ) {
+ rc = getaddrinfo(hostname, nullptr, nullptr, &hres);
+ if (rc != 0 || hres == nullptr ) {
debug((char *) "%s| %s: ERROR: resolving hostname with getaddrinfo: %s failed\n",
LogTime(), PROGRAM, gai_strerror(rc));
fprintf(stderr,
"%s| %s: ERROR: resolving hostname with getaddrinfo: %s failed\n",
LogTime(), PROGRAM, gai_strerror(rc));
- return NULL;
+ return nullptr;
}
hres_list = hres;
count = 0;
hres_list = hres_list->ai_next;
}
rc = getnameinfo(hres->ai_addr, hres->ai_addrlen, hostname,
- sizeof(hostname), NULL, 0, 0);
+ sizeof(hostname), nullptr, 0, 0);
if (rc != 0) {
debug((char *) "%s| %s: ERROR: resolving ip address with getnameinfo: %s failed\n",
LogTime(), PROGRAM, gai_strerror(rc));
"%s| %s: ERROR: resolving ip address with getnameinfo: %s failed\n",
LogTime(), PROGRAM, gai_strerror(rc));
freeaddrinfo(hres);
- return NULL;
+ return nullptr;
}
freeaddrinfo(hres);
hostname[sizeof(hostname)-1] = '\0';
*/
krb5_error_code krb5_read_keytab(krb5_context context, char *name, krb5_kt_list *list)
{
- krb5_kt_list lp = NULL, tail = NULL, back = NULL;
+ krb5_kt_list lp = nullptr, tail = nullptr, back = nullptr;
krb5_keytab kt;
krb5_keytab_entry *entry;
krb5_kt_cursor cursor;
}
if (!tail)
tail = lp;
- lp->next = NULL;
+ lp->next = nullptr;
lp->entry = entry;
}
xfree(entry);
retval = 0;
else {
krb5_free_kt_list(context, tail);
- tail = NULL;
+ tail = nullptr;
if (back)
- back->next = NULL;
+ back->next = nullptr;
}
}
if (!*list)
*/
krb5_error_code krb5_write_keytab(krb5_context context, krb5_kt_list list, char *name)
{
- krb5_keytab kt;
char ktname[MAXPATHLEN+sizeof("MEMORY:")+1];
krb5_error_code retval = 0;
snprintf(ktname, sizeof(ktname), "%s", name);
- retval = krb5_kt_resolve(context, ktname, &kt);
+ retval = krb5_kt_resolve(context, ktname, &memory_keytab);
if (retval)
return retval;
for (krb5_kt_list lp = list; lp; lp = lp->next) {
- retval = krb5_kt_add_entry(context, kt, lp->entry);
+ retval = krb5_kt_add_entry(context, memory_keytab, lp->entry);
if (retval)
break;
}
{
char buf[MAX_AUTHTOKEN_LEN];
char *c, *p;
- char *user = NULL;
- char *rfc_user = NULL;
+ char *user = nullptr;
+ char *rfc_user = nullptr;
#if HAVE_PAC_SUPPORT
char ad_groups[MAX_PAC_GROUP_SIZE];
- char *ag=NULL;
+ char *ag=nullptr;
krb5_pac pac;
#if USE_HEIMDAL_KRB5
gss_buffer_desc data_set = GSS_C_EMPTY_BUFFER;
gss_buffer_desc type_id = GSS_C_EMPTY_BUFFER;
#endif
#endif
- krb5_context context = NULL;
+ krb5_context context = nullptr;
krb5_error_code ret;
long length = 0;
static int err = 0;
int opt, log = 0, norealm = 0;
OM_uint32 ret_flags = 0, spnego_flag = 0;
- char *service_name = (char *) "HTTP", *host_name = NULL;
- char *token = NULL;
- char *service_principal = NULL;
- char *keytab_name = NULL;
- char *keytab_name_env = NULL;
- char default_keytab[MAXPATHLEN];
+ char *service_name = (char *) "HTTP", *host_name = nullptr;
+ char *token = nullptr;
+ char *service_principal = nullptr;
+ char *keytab_name = nullptr;
+ char *keytab_name_env = nullptr;
+ char default_keytab[MAXPATHLEN] = {};
#if HAVE_KRB5_MEMORY_KEYTAB
- char *memory_keytab_name = NULL;
+ char *memory_keytab_name = nullptr;
+ char *memory_keytab_name_env = nullptr;
#endif
- char *rcache_type = NULL;
- char *rcache_type_env = NULL;
- char *rcache_dir = NULL;
- char *rcache_dir_env = NULL;
+ char *rcache_type = nullptr;
+ char *rcache_type_env = nullptr;
+ char *rcache_dir = nullptr;
+ char *rcache_dir_env = nullptr;
OM_uint32 major_status, minor_status;
gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
gss_name_t client_name = GSS_C_NO_NAME;
gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
- const unsigned char *kerberosToken = NULL;
- const unsigned char *spnegoToken = NULL;
+ const unsigned char *kerberosToken = nullptr;
+ const unsigned char *spnegoToken = nullptr;
size_t spnegoTokenLength = 0;
- setbuf(stdout, NULL);
- setbuf(stdin, NULL);
+ setbuf(stdout, nullptr);
+ setbuf(stdin, nullptr);
while (-1 != (opt = getopt(argc, argv, "dirs:k:c:t:"))) {
switch (opt) {
keytab_name = xstrdup(optarg);
else {
fprintf(stderr, "ERROR: keytab file not given\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
/*
* Some sanity checks
fprintf(stderr, "ERROR: keytab file %s does not exist\n",keytab_name);
else
fprintf(stderr, "ERROR: Error %s during stat of keytab file %s\n",strerror(errno),keytab_name);
- exit(1);
+ exit(EXIT_FAILURE);
} else if (!S_ISREG(fstat.st_mode)) {
fprintf(stderr, "ERROR: keytab file %s is not a file\n",keytab_name);
- exit(1);
+ exit(EXIT_FAILURE);
}
#endif
#if HAVE_UNISTD_H
if (access(ktp, R_OK)) {
fprintf(stderr, "ERROR: keytab file %s is not accessible\n",keytab_name);
- exit(1);
+ exit(EXIT_FAILURE);
}
#endif
break;
rcache_dir = xstrdup(optarg);
else {
fprintf(stderr, "ERROR: replay cache directory not given\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
/*
* Some sanity checks
fprintf(stderr, "ERROR: replay cache directory %s does not exist\n",rcache_dir);
else
fprintf(stderr, "ERROR: Error %s during stat of replay cache directory %s\n",strerror(errno),rcache_dir);
- exit(1);
+ exit(EXIT_FAILURE);
} else if (!S_ISDIR(dstat.st_mode)) {
fprintf(stderr, "ERROR: replay cache directory %s is not a directory\n",rcache_dir);
- exit(1);
+ exit(EXIT_FAILURE);
}
#endif
#if HAVE_UNISTD_H
if (access(rcache_dir, W_OK)) {
fprintf(stderr, "ERROR: replay cache directory %s is not accessible\n",rcache_dir);
- exit(1);
+ exit(EXIT_FAILURE);
}
#endif
break;
rcache_type = xstrdup(optarg);
else {
fprintf(stderr, "ERROR: replay cache type not given\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
break;
case 's':
service_principal = xstrdup(optarg);
else {
fprintf(stderr, "ERROR: service principal not given\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
break;
default:
fprintf(stderr,
"The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
- exit(0);
+ exit(EXIT_SUCCESS);
}
}
"%s| %s: FATAL: Local hostname could not be determined. Please specify the service principal\n",
LogTime(), PROGRAM);
fprintf(stdout, "BH hostname error\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
service.value = xmalloc(strlen(service_name) + strlen(host_name) + 2);
snprintf((char *) service.value, strlen(service_name) + strlen(host_name) + 2,
debug((char *) "%s| %s: ERROR: Writing list into keytab %s\n",
LogTime(), PROGRAM, memory_keytab_name);
} else {
- keytab_name_env = (char *) xmalloc(strlen("KRB5_KTNAME=")+strlen(memory_keytab_name)+1);
- strcpy(keytab_name_env, "KRB5_KTNAME=");
- strcat(keytab_name_env, memory_keytab_name);
- putenv(keytab_name_env);
+ memory_keytab_name_env = (char *) xmalloc(strlen("KRB5_KTNAME=")+strlen(memory_keytab_name)+1);
+ strcpy(memory_keytab_name_env, "KRB5_KTNAME=");
+ strcat(memory_keytab_name_env, memory_keytab_name);
+ putenv(memory_keytab_name_env);
xfree(keytab_name);
keytab_name = xstrdup(memory_keytab_name);
debug((char *) "%s| %s: INFO: Changed keytab to %s\n",
gsskrb5_register_acceptor_identity(keytab_name);
#endif
while (1) {
- if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
+ if (fgets(buf, sizeof(buf) - 1, stdin) == nullptr) {
if (ferror(stdin)) {
debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n",
LogTime(), PROGRAM, ferror(stdin),
strerror(ferror(stdin)));
fprintf(stdout, "BH input error\n");
- exit(1); /* BIIG buffer */
+ exit(EXIT_FAILURE); /* BIIG buffer */
}
fprintf(stdout, "BH input error\n");
- exit(0);
+ exit(EXIT_SUCCESS);
}
c = (char *) memchr(buf, '\n', sizeof(buf) - 1);
if (c) {
if (client_name)
gss_release_name(&minor_status, &client_name);
if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&minor_status, &gss_context, NULL);
+ gss_delete_sec_context(&minor_status, &gss_context, nullptr);
if (kerberosToken) {
/* Allocated by parseNegTokenInit, but no matching free function exists.. */
if (!spnego_flag)
xfree(spnegoToken);
}
xfree(token);
+ xfree(rcache_type);
+ xfree(rcache_type_env);
+ xfree(rcache_dir);
+ xfree(rcache_dir_env);
+ xfree(keytab_name);
+ xfree(keytab_name_env);
+#if HAVE_KRB5_MEMORY_KEYTAB
+ krb5_kt_close(context, memory_keytab);
+ xfree(memory_keytab_name);
+ xfree(memory_keytab_name_env);
+#endif
+ xfree(rfc_user);
fprintf(stdout, "BH quit command\n");
- exit(0);
+ exit(EXIT_SUCCESS);
}
if (strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2)) {
debug((char *) "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
}
if (!strncmp(buf, "YR", 2)) {
if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&minor_status, &gss_context, NULL);
+ gss_delete_sec_context(&minor_status, &gss_context, nullptr);
gss_context = GSS_C_NO_CONTEXT;
}
if (strlen(buf) <= 3) {
fprintf(stdout, "BH Invalid negotiate request\n");
continue;
}
- const uint8_t *b64Token = reinterpret_cast<const uint8_t*>(buf+3);
+ const char *b64Token = buf+3;
const size_t srcLen = strlen(buf+3);
input_token.length = BASE64_DECODE_LENGTH(srcLen);
debug((char *) "%s| %s: DEBUG: Decode '%s' (decoded length estimate: %d).\n",
major_status =
gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
- GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, NULL, NULL);
+ GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, nullptr, nullptr);
if (check_gss_err(major_status, minor_status, "gss_acquire_cred()", log, 1))
goto cleanup;
server_creds,
&input_token,
GSS_C_NO_CHANNEL_BINDINGS,
- &client_name, NULL, &output_token, &ret_flags, NULL, NULL);
+ &client_name, nullptr, &output_token, &ret_flags, nullptr, nullptr);
if (output_token.length) {
spnegoToken = (const unsigned char *) output_token.value;
spnegoTokenLength = output_token.length;
token = (char *) xmalloc((size_t)base64_encode_len(spnegoTokenLength));
- if (token == NULL) {
+ if (token == nullptr) {
debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
fprintf(stdout, "BH Not enough memory\n");
goto cleanup;
}
struct base64_encode_ctx tokCtx;
base64_encode_init(&tokCtx);
- size_t blen = base64_encode_update(&tokCtx, reinterpret_cast<uint8_t*>(token), spnegoTokenLength, reinterpret_cast<const uint8_t*>(spnegoToken));
- blen += base64_encode_final(&tokCtx, reinterpret_cast<uint8_t*>(token)+blen);
+ size_t blen = base64_encode_update(&tokCtx, token, spnegoTokenLength, reinterpret_cast<const uint8_t*>(spnegoToken));
+ blen += base64_encode_final(&tokCtx, token+blen);
token[blen] = '\0';
if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log, 1))
goto cleanup;
if (major_status & GSS_S_CONTINUE_NEEDED) {
debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
- fprintf(stdout, "TT %s\n", token);
+ fprintf(stdout, "TT token=%s\n", token);
goto cleanup;
}
gss_release_buffer(&minor_status, &output_token);
major_status =
gss_display_name(&minor_status, client_name, &output_token,
- NULL);
+ nullptr);
if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1))
goto cleanup;
user = (char *) xmalloc(output_token.length + 1);
- if (user == NULL) {
+ if (user == nullptr) {
debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
fprintf(stdout, "BH Not enough memory\n");
goto cleanup;
}
memcpy(user, output_token.value, output_token.length);
user[output_token.length] = '\0';
- if (norealm && (p = strchr(user, '@')) != NULL) {
+ if (norealm && (p = strchr(user, '@')) != nullptr) {
*p = '\0';
}
#endif
rfc_user = rfc1738_escape(user);
#if HAVE_PAC_SUPPORT
- fprintf(stdout, "AF %s %s %s\n", token, rfc_user, ag?ag:"group=");
+ fprintf(stdout, "OK token=%s user=%s %s\n", token, rfc_user, ag?ag:"group=");
#else
- fprintf(stdout, "AF %s %s\n", token, rfc_user);
+ fprintf(stdout, "OK token=%s user=%s\n", token, rfc_user);
#endif
- debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc_user);
+ debug((char *) "%s| %s: DEBUG: OK token=%s user=%s\n", LogTime(), PROGRAM, token, rfc_user);
if (log)
fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
PROGRAM, rfc_user);
goto cleanup;
if (major_status & GSS_S_CONTINUE_NEEDED) {
debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
- fprintf(stdout, "NA %s\n", token);
+ // XXX: where to get the server token for delivery to client? token is nullptr here.
+ fprintf(stdout, "ERR\n");
goto cleanup;
}
gss_release_buffer(&minor_status, &output_token);
major_status =
gss_display_name(&minor_status, client_name, &output_token,
- NULL);
+ nullptr);
if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1))
goto cleanup;
* Return dummy token AA. May need an extra return tag then AF
*/
user = (char *) xmalloc(output_token.length + 1);
- if (user == NULL) {
+ if (user == nullptr) {
debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
fprintf(stdout, "BH Not enough memory\n");
goto cleanup;
}
memcpy(user, output_token.value, output_token.length);
user[output_token.length] = '\0';
- if (norealm && (p = strchr(user, '@')) != NULL) {
+ if (norealm && (p = strchr(user, '@')) != nullptr) {
*p = '\0';
}
rfc_user = rfc1738_escape(user);
#if HAVE_PAC_SUPPORT
- fprintf(stdout, "AF %s %s %s\n", "AA==", rfc_user, ag?ag:"group=");
+ fprintf(stdout, "OK token=%s user=%s %s\n", "AA==", rfc_user, ag?ag:"group=");
#else
- fprintf(stdout, "AF %s %s\n", "AA==", rfc_user);
+ fprintf(stdout, "OK token=%s user=%s\n", "AA==", rfc_user);
#endif
- debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, "AA==", rfc_user);
+ debug((char *) "%s| %s: DEBUG: OK token=%s user=%s\n", LogTime(), PROGRAM, "AA==", rfc_user);
if (log)
fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
PROGRAM, rfc_user);
safe_free(user);
continue;
}
+ return EXIT_SUCCESS;
}
#else
#include <cstdlib>
while (1) {
if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
fprintf(stdout, "BH input error\n");
- exit(0);
+ exit(EXIT_SUCCESS);
}
fprintf(stdout, "BH Kerberos authentication not supported\n");
}
+ return EXIT_SUCCESS;
}
#endif /* HAVE_GSSAPI */