Инструменты пользователя

Инструменты сайта


dev:cpp:gssapi_krb5:sozdanie_stroki_dlja_negotiate_autentifikacii

====== Создание строки для Negotiate аутентификации ====== Версии (**Ubuntu 8.10**): * запуск: **libkrb53**; * сборка: **libkrb5-dev**. ===== Код ===== <code c> /*************************************************************************** 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; } </code> Код функции **base64_encode** взят из проекта {{http://curl.haxx.se/|libcurl}} (функция //Curl_base64_encode// в файле //base64.c//). <code 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 ---- */ </code> ===== Использование ===== После включения приведённого кода в свой проект, можно использовать функцию **getNegotiateToken**, например, для формирования заголовка //Proxy-Authorization//: <code c> char *negotiateString; negotiateString=getNegotiateToken("HTTP","proxyserver"); if(negotiateString) { printf("Proxy-Authorization: Negotiate %s\r\n",negotiateString); free(negotiateString); } </code> Разумеется, на момент вызова функции уже должен быть получен билет Kerberos. ===== Замечания ===== * Строка, которую возвращает эта функция отличается от таковой в Mozilla Firefox (по-моему, Mozilla всё-таки использует SPNEGO). Однако, насколько я понял, верны обе. По-крайней мере, так считает helper от Squid //squid_kerb_auth//. * Несмотря на то, что кусок кода подсмотрен в libcurl, сама библиотека по невыясненным причинам не хочет авторизовываться методом Negotiate. ===== TODO ===== * Разобраться и по возможности добавить дополнительное преобразование SPNEGO. Функции для этого есть в //spnegohelp// (взять можно из того же //squid_kerb_auth//). При первой попытке реализации сервер при преобразовании SPNEGO возвращает //rc=101// (собственно, с Firefox тоже самое), при этом контекст gss становится неверным (а вот с этим в Firefox всё нормально). ... Или оно вообще не нужно?

Дискуссия

Enter your comment
 
dev/cpp/gssapi_krb5/sozdanie_stroki_dlja_negotiate_autentifikacii.txt · Последние изменения: 16.11.2009 17:26 (внешнее изменение)

Инструменты страницы