Annotation of embedaddon/curl/tests/libtest/stub_gssapi.c, revision 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>