Annotation of embedaddon/curl/tests/libtest/stub_gssapi.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 2017-2019, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: 
                     23: /* Only provides the bare minimum to link with libcurl */
                     24: 
                     25: #include <stdio.h>
                     26: #include <stdlib.h>
                     27: #include <string.h>
                     28: 
                     29: #include "stub_gssapi.h"
                     30: 
                     31: /* !checksrc! disable SNPRINTF all */
                     32: 
                     33: #define MAX_CREDS_LENGTH 250
                     34: #define APPROX_TOKEN_LEN 250
                     35: 
                     36: enum min_err_code {
                     37:     GSS_OK = 0,
                     38:     GSS_NO_MEMORY,
                     39:     GSS_INVALID_ARGS,
                     40:     GSS_INVALID_CREDS,
                     41:     GSS_INVALID_CTX,
                     42:     GSS_SERVER_ERR,
                     43:     GSS_NO_MECH,
                     44:     GSS_LAST
                     45: };
                     46: 
                     47: static const char *min_err_table[] = {
                     48:   "stub-gss: no error",
                     49:   "stub-gss: no memory",
                     50:   "stub-gss: invalid arguments",
                     51:   "stub-gss: invalid credentials",
                     52:   "stub-gss: invalid context",
                     53:   "stub-gss: server returned error",
                     54:   "stub-gss: cannot find a mechanism",
                     55:   NULL
                     56: };
                     57: 
                     58: struct gss_ctx_id_t_desc_struct {
                     59:   enum { NONE, KRB5, NTLM1, NTLM3 } sent;
                     60:   int have_krb5;
                     61:   int have_ntlm;
                     62:   OM_uint32 flags;
                     63:   char creds[MAX_CREDS_LENGTH];
                     64: };
                     65: 
                     66: OM_uint32 gss_init_sec_context(OM_uint32 *min,
                     67:             gss_const_cred_id_t initiator_cred_handle,
                     68:             gss_ctx_id_t *context_handle,
                     69:             gss_const_name_t target_name,
                     70:             const gss_OID mech_type,
                     71:             OM_uint32 req_flags,
                     72:             OM_uint32 time_req,
                     73:             const gss_channel_bindings_t input_chan_bindings,
                     74:             const gss_buffer_t input_token,
                     75:             gss_OID *actual_mech_type,
                     76:             gss_buffer_t output_token,
                     77:             OM_uint32 *ret_flags,
                     78:             OM_uint32 *time_rec)
                     79: {
                     80:   /* The token will be encoded in base64 */
                     81:   int length = APPROX_TOKEN_LEN * 3 / 4;
                     82:   int used = 0;
                     83:   char *token = NULL;
                     84:   const char *creds = NULL;
                     85:   gss_ctx_id_t ctx = NULL;
                     86: 
                     87:   (void)initiator_cred_handle;
                     88:   (void)mech_type;
                     89:   (void)time_req;
                     90:   (void)input_chan_bindings;
                     91:   (void)actual_mech_type;
                     92: 
                     93:   if(!min)
                     94:     return GSS_S_FAILURE;
                     95: 
                     96:   *min = 0;
                     97: 
                     98:   if(!context_handle || !target_name || !output_token) {
                     99:     *min = GSS_INVALID_ARGS;
                    100:     return GSS_S_FAILURE;
                    101:   }
                    102: 
                    103:   creds = getenv("CURL_STUB_GSS_CREDS");
                    104:   if(!creds || strlen(creds) >= MAX_CREDS_LENGTH) {
                    105:     *min = GSS_INVALID_CREDS;
                    106:     return GSS_S_FAILURE;
                    107:   }
                    108: 
                    109:   ctx = *context_handle;
                    110:   if(ctx && strcmp(ctx->creds, creds)) {
                    111:     *min = GSS_INVALID_CREDS;
                    112:     return GSS_S_FAILURE;
                    113:   }
                    114: 
                    115:   output_token->length = 0;
                    116:   output_token->value = NULL;
                    117: 
                    118:   if(input_token && input_token->length) {
                    119:     if(!ctx) {
                    120:       *min = GSS_INVALID_CTX;
                    121:       return GSS_S_FAILURE;
                    122:     }
                    123: 
                    124:     /* Server response, either D (RA==) or C (Qw==) */
                    125:     if(((char *) input_token->value)[0] == 'D') {
                    126:       /* Done */
                    127:       switch(ctx->sent) {
                    128:       case KRB5:
                    129:       case NTLM3:
                    130:         if(ret_flags)
                    131:           *ret_flags = ctx->flags;
                    132:         if(time_rec)
                    133:           *time_rec = GSS_C_INDEFINITE;
                    134:         return GSS_S_COMPLETE;
                    135:       default:
                    136:         *min = GSS_SERVER_ERR;
                    137:         return GSS_S_FAILURE;
                    138:       }
                    139:     }
                    140: 
                    141:     if(((char *) input_token->value)[0] != 'C') {
                    142:       /* We only support Done or Continue */
                    143:       *min = GSS_SERVER_ERR;
                    144:       return GSS_S_FAILURE;
                    145:     }
                    146: 
                    147:     /* Continue */
                    148:     switch(ctx->sent) {
                    149:     case KRB5:
                    150:       /* We sent KRB5 and it failed, let's try NTLM */
                    151:       if(ctx->have_ntlm) {
                    152:         ctx->sent = NTLM1;
                    153:         break;
                    154:       }
                    155:       else {
                    156:         *min = GSS_SERVER_ERR;
                    157:         return GSS_S_FAILURE;
                    158:       }
                    159:     case NTLM1:
                    160:       ctx->sent = NTLM3;
                    161:       break;
                    162:     default:
                    163:       *min = GSS_SERVER_ERR;
                    164:       return GSS_S_FAILURE;
                    165:     }
                    166:   }
                    167:   else {
                    168:     if(ctx) {
                    169:       *min = GSS_INVALID_CTX;
                    170:       return GSS_S_FAILURE;
                    171:     }
                    172: 
                    173:     ctx = (gss_ctx_id_t) calloc(sizeof(*ctx), 1);
                    174:     if(!ctx) {
                    175:       *min = GSS_NO_MEMORY;
                    176:       return GSS_S_FAILURE;
                    177:     }
                    178: 
                    179:     if(strstr(creds, "KRB5"))
                    180:       ctx->have_krb5 = 1;
                    181: 
                    182:     if(strstr(creds, "NTLM"))
                    183:       ctx->have_ntlm = 1;
                    184: 
                    185:     if(ctx->have_krb5)
                    186:       ctx->sent = KRB5;
                    187:     else if(ctx->have_ntlm)
                    188:       ctx->sent = NTLM1;
                    189:     else {
                    190:       free(ctx);
                    191:       *min = GSS_NO_MECH;
                    192:       return GSS_S_FAILURE;
                    193:     }
                    194: 
                    195:     strcpy(ctx->creds, creds);
                    196:     ctx->flags = req_flags;
                    197:   }
                    198: 
                    199:   token = malloc(length);
                    200:   if(!token) {
                    201:     free(ctx);
                    202:     *min = GSS_NO_MEMORY;
                    203:     return GSS_S_FAILURE;
                    204:   }
                    205: 
                    206:   /* Token format: creds:target:type:padding */
                    207:   /* Note: this is using the *real* snprintf() and not the curl provided
                    208:      one */
                    209:   used = snprintf(token, length, "%s:%s:%d:", creds,
                    210:                   (char *) target_name, ctx->sent);
                    211: 
                    212:   if(used >= length) {
                    213:     free(token);
                    214:     free(ctx);
                    215:     *min = GSS_NO_MEMORY;
                    216:     return GSS_S_FAILURE;
                    217:   }
                    218: 
                    219:   /* Overwrite null terminator */
                    220:   memset(token + used, 'A', length - used);
                    221: 
                    222:   *context_handle = ctx;
                    223: 
                    224:   output_token->value = token;
                    225:   output_token->length = length;
                    226: 
                    227:   return GSS_S_CONTINUE_NEEDED;
                    228: }
                    229: 
                    230: OM_uint32 gss_delete_sec_context(OM_uint32 *min,
                    231:                                  gss_ctx_id_t *context_handle,
                    232:                                  gss_buffer_t output_token)
                    233: {
                    234:   (void)output_token;
                    235: 
                    236:   if(!min)
                    237:     return GSS_S_FAILURE;
                    238: 
                    239:   if(!context_handle) {
                    240:     *min = GSS_INVALID_CTX;
                    241:     return GSS_S_FAILURE;
                    242:   }
                    243: 
                    244:   free(*context_handle);
                    245:   *context_handle = NULL;
                    246:   *min = 0;
                    247: 
                    248:   return GSS_S_COMPLETE;
                    249: }
                    250: 
                    251: OM_uint32 gss_release_buffer(OM_uint32 *min,
                    252:                              gss_buffer_t buffer)
                    253: {
                    254:   if(min)
                    255:     *min = 0;
                    256: 
                    257:   if(buffer && buffer->length) {
                    258:     free(buffer->value);
                    259:     buffer->length = 0;
                    260:   }
                    261: 
                    262:   return GSS_S_COMPLETE;
                    263: }
                    264: 
                    265: OM_uint32 gss_import_name(OM_uint32 *min,
                    266:                           const gss_buffer_t input_name_buffer,
                    267:                           const gss_OID input_name_type,
                    268:                           gss_name_t *output_name)
                    269: {
                    270:   char *name = NULL;
                    271:   (void)input_name_type;
                    272: 
                    273:   if(!min)
                    274:     return GSS_S_FAILURE;
                    275: 
                    276:   if(!input_name_buffer || !output_name) {
                    277:     *min = GSS_INVALID_ARGS;
                    278:     return GSS_S_FAILURE;
                    279:   }
                    280: 
                    281:   name = strndup(input_name_buffer->value, input_name_buffer->length);
                    282:   if(!name) {
                    283:     *min = GSS_NO_MEMORY;
                    284:     return GSS_S_FAILURE;
                    285:   }
                    286: 
                    287:   *output_name = (gss_name_t) name;
                    288:   *min = 0;
                    289: 
                    290:   return GSS_S_COMPLETE;
                    291: }
                    292: 
                    293: OM_uint32 gss_release_name(OM_uint32 *min,
                    294:                            gss_name_t *input_name)
                    295: {
                    296:   if(min)
                    297:     *min = 0;
                    298: 
                    299:   if(input_name)
                    300:     free(*input_name);
                    301: 
                    302:   return GSS_S_COMPLETE;
                    303: }
                    304: 
                    305: OM_uint32 gss_display_status(OM_uint32 *min,
                    306:                              OM_uint32 status_value,
                    307:                              int status_type,
                    308:                              const gss_OID mech_type,
                    309:                              OM_uint32 *message_context,
                    310:                              gss_buffer_t status_string)
                    311: {
                    312:   const char maj_str[] = "Stub GSS error";
                    313:   (void)mech_type;
                    314:   if(min)
                    315:     *min = 0;
                    316: 
                    317:   if(message_context)
                    318:     *message_context = 0;
                    319: 
                    320:   if(status_string) {
                    321:     status_string->value = NULL;
                    322:     status_string->length = 0;
                    323: 
                    324:     if(status_value >= GSS_LAST)
                    325:       return GSS_S_FAILURE;
                    326: 
                    327:     switch(status_type) {
                    328:       case GSS_C_GSS_CODE:
                    329:         status_string->value = strdup(maj_str);
                    330:         break;
                    331:       case GSS_C_MECH_CODE:
                    332:         status_string->value = strdup(min_err_table[status_value]);
                    333:         break;
                    334:       default:
                    335:         return GSS_S_FAILURE;
                    336:     }
                    337: 
                    338:     if(status_string->value)
                    339:       status_string->length = strlen(status_string->value);
                    340:     else
                    341:       return GSS_S_FAILURE;
                    342:   }
                    343: 
                    344:   return GSS_S_COMPLETE;
                    345: }
                    346: 
                    347: /* Stubs returning error */
                    348: 
                    349: OM_uint32 gss_display_name(OM_uint32 *min,
                    350:                            gss_const_name_t input_name,
                    351:                            gss_buffer_t output_name_buffer,
                    352:                            gss_OID *output_name_type)
                    353: {
                    354:   (void)min;
                    355:   (void)input_name;
                    356:   (void)output_name_buffer;
                    357:   (void)output_name_type;
                    358:   return GSS_S_FAILURE;
                    359: }
                    360: 
                    361: OM_uint32 gss_inquire_context(OM_uint32 *min,
                    362:                               gss_const_ctx_id_t context_handle,
                    363:                               gss_name_t *src_name,
                    364:                               gss_name_t *targ_name,
                    365:                               OM_uint32 *lifetime_rec,
                    366:                               gss_OID *mech_type,
                    367:                               OM_uint32 *ctx_flags,
                    368:                               int *locally_initiated,
                    369:                               int *open_context)
                    370: {
                    371:   (void)min;
                    372:   (void)context_handle;
                    373:   (void)src_name;
                    374:   (void)targ_name;
                    375:   (void)lifetime_rec;
                    376:   (void)mech_type;
                    377:   (void)ctx_flags;
                    378:   (void)locally_initiated;
                    379:   (void)open_context;
                    380:   return GSS_S_FAILURE;
                    381: }
                    382: 
                    383: OM_uint32 gss_wrap(OM_uint32 *min,
                    384:                    gss_const_ctx_id_t context_handle,
                    385:                    int conf_req_flag,
                    386:                    gss_qop_t qop_req,
                    387:                    const gss_buffer_t input_message_buffer,
                    388:                    int *conf_state,
                    389:                    gss_buffer_t output_message_buffer)
                    390: {
                    391:   (void)min;
                    392:   (void)context_handle;
                    393:   (void)conf_req_flag;
                    394:   (void)qop_req;
                    395:   (void)input_message_buffer;
                    396:   (void)conf_state;
                    397:   (void)output_message_buffer;
                    398:   return GSS_S_FAILURE;
                    399: }
                    400: 
                    401: OM_uint32 gss_unwrap(OM_uint32 *min,
                    402:                      gss_const_ctx_id_t context_handle,
                    403:                      const gss_buffer_t input_message_buffer,
                    404:                      gss_buffer_t output_message_buffer,
                    405:                      int *conf_state,
                    406:                      gss_qop_t *qop_state)
                    407: {
                    408:   (void)min;
                    409:   (void)context_handle;
                    410:   (void)input_message_buffer;
                    411:   (void)output_message_buffer;
                    412:   (void)conf_state;
                    413:   (void)qop_state;
                    414:   return GSS_S_FAILURE;
                    415: }
                    416: 
                    417: OM_uint32 gss_seal(OM_uint32 *min,
                    418:                    gss_ctx_id_t context_handle,
                    419:                    int conf_req_flag,
                    420:                    int qop_req,
                    421:                    gss_buffer_t input_message_buffer,
                    422:                    int *conf_state,
                    423:                    gss_buffer_t output_message_buffer)
                    424: {
                    425:   (void)min;
                    426:   (void)context_handle;
                    427:   (void)conf_req_flag;
                    428:   (void)qop_req;
                    429:   (void)input_message_buffer;
                    430:   (void)conf_state;
                    431:   (void)output_message_buffer;
                    432:   return GSS_S_FAILURE;
                    433: }
                    434: 
                    435: OM_uint32 gss_unseal(OM_uint32 *min,
                    436:                      gss_ctx_id_t context_handle,
                    437:                      gss_buffer_t input_message_buffer,
                    438:                      gss_buffer_t output_message_buffer,
                    439:                      int *conf_state,
                    440:                      int *qop_state)
                    441: {
                    442:   (void)min;
                    443:   (void)context_handle;
                    444:   (void)input_message_buffer;
                    445:   (void)output_message_buffer;
                    446:   (void)conf_state;
                    447:   (void)qop_state;
                    448:   return GSS_S_FAILURE;
                    449: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>