📄 squid_kerb_auth.c
字号:
/* * ----------------------------------------------------------------------------- * * Author: Markus Moeller (markus_moeller at compuserve.com) * * Copyright (C) 2007 Markus Moeller. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * ----------------------------------------------------------------------------- *//* * Hosted at http://sourceforge.net/projects/squidkerbauth */#include <string.h>#include <stdio.h>#include <stdlib.h>#include <netdb.h>#include <unistd.h>#include <time.h>#include <sys/time.h>#include "base64.h"#ifndef HAVE_SPNEGO#include "spnegohelp.h"#endif#ifndef MAXHOSTNAMELEN#define MAXHOSTNAMELEN HOST_NAME_MAX#endif#define PROGRAM "squid_kerb_auth"#ifdef HEIMDAL#include <gssapi.h>#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE#else#include <gssapi/gssapi.h>#ifndef SOLARIS_11#include <gssapi/gssapi_generic.h>#else#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE#endif#endif#include <krb5.h>int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int loging);char *gethost_name(void);static const char *LogTime(void);static const unsigned char ntlmProtocol [] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};static const char *LogTime(){ struct tm *tm; struct timeval now; static time_t last_t = 0; static char buf[128]; gettimeofday(&now, NULL); if (now.tv_sec != last_t) { tm = localtime(&now.tv_sec); strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); last_t = now.tv_sec; } return buf;}char *gethost_name(void) { char hostname[MAXHOSTNAMELEN]; struct addrinfo *hres=NULL, *hres_list; int rc,count; rc = gethostname(hostname,MAXHOSTNAMELEN); if (rc) { fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n", LogTime(), PROGRAM, hostname); return NULL; } rc = getaddrinfo(hostname,NULL,NULL,&hres); if (rc != 0) { fprintf(stderr, "%s| %s: error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc)); return NULL; } hres_list=hres; count=0; while (hres_list) { count++; hres_list=hres_list->ai_next; } rc = getnameinfo (hres->ai_addr, hres->ai_addrlen,hostname, sizeof (hostname), NULL, 0, 0); if (rc != 0) { fprintf(stderr, "%s| %s: error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc)); freeaddrinfo(hres); return NULL ; } freeaddrinfo(hres); hostname[MAXHOSTNAMELEN]='\0'; return(strdup(hostname));}int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int loging) { if (GSS_ERROR(major_status)) { OM_uint32 maj_stat,min_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; char buf[1024]; size_t len; len = 0; msg_ctx = 0; while (!msg_ctx) { /* convert major status code (GSS-API error) to text */ maj_stat = gss_display_status(&min_stat, major_status, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); if (maj_stat == GSS_S_COMPLETE) { if (sizeof(buf) > len + status_string.length + 1) { sprintf(buf+len, "%s", (char*) status_string.value); len += status_string.length; } gss_release_buffer(&min_stat, &status_string); break; } gss_release_buffer(&min_stat, &status_string); } if (sizeof(buf) > len + 2) { sprintf(buf+len, "%s", ". "); len += 2; } msg_ctx = 0; while (!msg_ctx) { /* convert minor status code (underlying routine error) to text */ maj_stat = gss_display_status(&min_stat, minor_status, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); if (maj_stat == GSS_S_COMPLETE) { if (sizeof(buf) > len + status_string.length ) { sprintf(buf+len, "%s", (char*) status_string.value); len += status_string.length; } gss_release_buffer(&min_stat, &status_string); break; } gss_release_buffer(&min_stat, &status_string); } if (debug) fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, buf); fprintf(stdout, "NA %s failed: %s\n",function, buf); if (loging) fprintf(stderr, "%s| %s: User not authenticated\n", LogTime(), PROGRAM); return(1); } return(0);}int main(int argc, char * const argv[]){ char buf[6400]; char *c; int length=0; static int err=0; int opt, rc, debug=0, loging=0; OM_uint32 ret_flags=0, spnego_flag=0; char *service_name=(char *)"HTTP",*host_name=NULL; char *token = NULL; char *service_principal = NULL; 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_name_t server_name = GSS_C_NO_NAME; gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL; gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL; 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; size_t kerberosTokenLength = 0; const unsigned char *spnegoToken = NULL ; size_t spnegoTokenLength = 0; setbuf(stdout,NULL); setbuf(stdin,NULL); while (-1 != (opt = getopt(argc, argv, "dis:h"))) { switch (opt) { case 'd': debug = 1; break; case 'i': loging = 1; break; case 's': service_principal = strdup(optarg); break; case 'h': fprintf(stdout, "Usage: \n"); fprintf(stdout, "squid_kerb_auth -d [-s SPN]\n"); fprintf(stdout, "SPN = service principal name\n"); fprintf(stdout, "Can be set to GSS_C_NO_NAME to allow any entry from keytab\n"); fprintf(stdout, "default SPN is HTTP/fqdn@DEFAULT_REALM\n"); break; default: fprintf(stderr, "%s| %s: unknown option: -%c.\n", LogTime(), PROGRAM, opt); } } if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) { service.value = service_principal; service.length = strlen((char *)service.value); } else { host_name=gethost_name(); if ( !host_name ) { fprintf(stderr, "%s| %s: Local hostname could not be determined. Please specify the service principal\n", LogTime(), PROGRAM); exit(-1); } service.value = malloc(strlen(service_name)+strlen(host_name)+2); snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name); service.length = strlen((char *)service.value); } while (1) { if (fgets(buf, sizeof(buf)-1, stdin) == NULL) { if (ferror(stdin)) { if (debug) fprintf(stderr, "%s| %s: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin), strerror(ferror(stdin))); exit(1); /* BIIG buffer */ } exit(0); } c=memchr(buf,'\n',sizeof(buf)-1); if (c) { *c = '\0'; length = c-buf; } else { err = 1; } if (err) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -