ne_ssl_certificate *ne_ssl_cert_import(const char *data) { int ret; size_t len; unsigned char *der; gnutls_datum buffer = { NULL, 0 }; gnutls_x509_crt x5; if (gnutls_x509_crt_init(&x5) != 0) return NULL; /* decode the base64 to get the raw DER representation */ len = ne_unbase64(data, &der); if (len == 0) return NULL; buffer.data = der; buffer.size = len; ret = gnutls_x509_crt_import(x5, &buffer, GNUTLS_X509_FMT_DER); ne_free(der); if (ret < 0) { gnutls_x509_crt_deinit(x5); return NULL; } return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5); }
/* * Decodes BASE64 string into SSPI SecBuffer */ static int base64ToBuffer(const char *token, SecBufferDesc * secBufferDesc) { SecBuffer *buffer; if (getSingleBufferDescriptor(secBufferDesc, &buffer)) { return -1; } buffer->BufferType = SECBUFFER_TOKEN; buffer->cbBuffer = ne_unbase64(token, (unsigned char **) &buffer->pvBuffer); if (buffer->cbBuffer == 0) { NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: Unable to decode BASE64 SSPI token.\n"); return -1; } return 0; }
static int unbase64(void) { static const char *ts[] = { "", "a", "ab", "abc", "}bcd", "a}cd", "ab}d", "abc}", " ", "^bcd", "a^cd", "ab^d", "abc^", "====", "=bcd", "a=cd", "ab=d", "a==d", "a=c=", NULL }; size_t n; for (n = 0; ts[n]; n++) { unsigned char *tmp; ONV(ne_unbase64(ts[n], &tmp) != 0, ("invalid string `%s' was decoded", ts[n])); } return OK; }
/* Check that raw data 'raw', of length 'len', has base64 encoding * of 'expected'. */ static int b64_check(const unsigned char *raw, size_t len, const char *expected) { char *encoded = ne_base64(raw, len); unsigned char *decoded; size_t dlen; ONV(strcmp(encoded, expected), ("base64(\"%s\") gave \"%s\" not \"%s\"", raw, encoded, expected)); dlen = ne_unbase64(encoded, &decoded); ONV(dlen != len, ("decoded `%s' length was %" NE_FMT_SIZE_T " not %" NE_FMT_SIZE_T, expected, dlen, len)); ONV(memcmp(raw, decoded, dlen), ("decoded `%s' as `%.*s' not `%.*s'", expected, (int)dlen, decoded, (int)dlen, raw)); ne_free(decoded); ne_free(encoded); return OK; }
/* Continue a GSS-API Negotiate exchange, using input TOKEN if * non-NULL. Returns non-zero on error. */ static int continue_negotiate(auth_session *sess, const char *token) { unsigned int major, minor; gss_buffer_desc input = GSS_C_EMPTY_BUFFER; gss_buffer_desc output = GSS_C_EMPTY_BUFFER; unsigned char *bintoken = NULL; int ret; if (token) { input.length = ne_unbase64(token, &bintoken); if (input.length == 0) { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Invalid input [%s].\n", token); return -1; } input.value = bintoken; NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Continuation token [%s]\n", token); } else if (sess->gssctx != GSS_C_NO_CONTEXT) { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Reset incomplete context.\n"); gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER); } major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &sess->gssctx, sess->gssname, sess->gssmech, GSS_C_MUTUAL_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, &input, &sess->gssmech, &output, NULL, NULL); /* done with the input token. */ if (bintoken) ne_free(bintoken); if (GSS_ERROR(major)) { ne_buffer *err = ne_buffer_create(); int flag = 0; make_gss_error(err, &flag, major, GSS_C_GSS_CODE); make_gss_error(err, &flag, minor, GSS_C_MECH_CODE); NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Error: %s\n", err->data); ne_set_error(sess->sess, _("GSSAPI authentication error (%s)"), err->data); ne_buffer_destroy(err); return -1; } if (major == GSS_S_CONTINUE_NEEDED || major == GSS_S_COMPLETE) { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: init_sec_context OK. (major=%d)\n", major); ret = 0; } else { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Init failure %d.\n", major); ret = -1; } if (major != GSS_S_CONTINUE_NEEDED) { /* context no longer needed: destroy it */ gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER); } if (output.length) { sess->gssapi_token = ne_base64(output.value, output.length); NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Output token: [%s]\n", sess->gssapi_token); gss_release_buffer(&minor, &output); } else { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: No output token.\n"); } return ret; }