Версии (Ubuntu 8.10):
/*************************************************************************** negotiate.c Author : Blake-R (c) 2009 Last update : Птн Мар 13 15:08:11 MSK 2009 Licence : GPL v3 ***************************************************************************/ #include <stdio.h> #include <malloc.h> #include <string.h> #include <gssapi/gssapi.h> char * getNegotiateToken(const char *service,const char *server) { char *token=NULL; OM_uint32 major,minor; gss_buffer_desc gss_buffer; gss_name_t gss_name; gss_ctx_id_t gss_context=GSS_C_NO_CONTEXT; gss_buffer_desc gss_input_token=GSS_C_EMPTY_BUFFER; gss_buffer_desc gss_output_token=GSS_C_EMPTY_BUFFER; if(!service||!server) { fprintf(stderr,"Service and server values cannot be NULL!\n"); return NULL; } gss_buffer.length=strlen(service)+strlen(server)+2; gss_buffer.value=malloc(gss_buffer.length); if(!gss_buffer.value) { fprintf(stderr,"malloc() failed\n"); } else { sprintf(gss_buffer.value,"%s@%s",service,server); major=gss_import_name(&minor,&gss_buffer,GSS_C_NT_HOSTBASED_SERVICE,&gss_name); if(major!=GSS_S_COMPLETE) { fprintf(stderr,"gss_import_name() error: %#x\n",major); } else { major=gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL,&gss_context,gss_name,GSS_C_NO_OID, GSS_C_DELEG_FLAG,0,GSS_C_NO_CHANNEL_BINDINGS, &gss_input_token,NULL,&gss_output_token,NULL,NULL); if(major!=GSS_S_COMPLETE) { fprintf(stderr,"gss_init_sec_context() error: %#x\n",major); } else { if(gss_output_token.length==0) { fprintf(stderr,"Token don't need to be send."); } else { // TODO: Need to make SPNEGO token (spnegohelp) base64_encode(gss_output_token.value,gss_output_token.length,&token); } major=gss_delete_sec_context(&minor,&gss_context,GSS_C_NO_BUFFER); if(major!=GSS_S_COMPLETE) { fprintf(stderr,"gss_delete_sec_context() error: %#x\n",major); } } major=gss_release_name(&minor,&gss_name); if(major!=GSS_S_COMPLETE) { fprintf(stderr,"gss_release_name() error: %#x\n",major); } } free(gss_buffer.value); } return token; }
Код функции base64_encode взят из проекта libcurl (функция Curl_base64_encode в файле base64.c).
/* ---- Base64 Encoding/Decoding Table --- */ static const char table64[]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; size_t base64_encode(const char *inp, size_t insize, char **outptr) { unsigned char ibuf[3]; unsigned char obuf[4]; int i; int inputparts; char *output; char *base64data; char *indata = (char *)inp; *outptr = NULL; /* set to NULL in case of failure before we reach the end */ if(0 == insize) insize = strlen(indata); base64data = output = (char*)malloc(insize*4/3+4); if(NULL == output) return 0; while(insize > 0) { for (i = inputparts = 0; i < 3; i++) { if(insize > 0) { inputparts++; ibuf[i] = *indata; indata++; insize--; } else ibuf[i] = 0; } obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ ((ibuf[1] & 0xF0) >> 4)); obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ ((ibuf[2] & 0xC0) >> 6)); obuf[3] = (unsigned char) (ibuf[2] & 0x3F); switch(inputparts) { case 1: /* only one byte read */ snprintf(output, 5, "%c%c==", table64[obuf[0]], table64[obuf[1]]); break; case 2: /* two bytes read */ snprintf(output, 5, "%c%c%c=", table64[obuf[0]], table64[obuf[1]], table64[obuf[2]]); break; default: snprintf(output, 5, "%c%c%c%c", table64[obuf[0]], table64[obuf[1]], table64[obuf[2]], table64[obuf[3]] ); break; } output += 4; } *output=0; *outptr = base64data; /* make it return the actual data memory */ return strlen(base64data); /* return the length of the new data */ } /* ---- End of Base64 Encoding ---- */
После включения приведённого кода в свой проект, можно использовать функцию getNegotiateToken, например, для формирования заголовка Proxy-Authorization:
char *negotiateString; negotiateString=getNegotiateToken("HTTP","proxyserver"); if(negotiateString) { printf("Proxy-Authorization: Negotiate %s\r\n",negotiateString); free(negotiateString); }
Разумеется, на момент вызова функции уже должен быть получен билет Kerberos.
Дискуссия