/* Read the contents of file FILENAME into *DATUM. */ static int read_to_datum(const char *filename, gnutls_datum *datum) { FILE *f = fopen(filename, "r"); ne_buffer *buf; char tmp[4192]; size_t len; if (!f) { return -1; } buf = ne_buffer_ncreate(8192); while ((len = fread(tmp, 1, sizeof tmp, f)) > 0) { ne_buffer_append(buf, tmp, len); } if (!feof(f)) { fclose(f); ne_buffer_destroy(buf); return -1; } fclose(f); datum->size = ne_buffer_size(buf); datum->data = (unsigned char *)ne_buffer_finish(buf); return 0; }
char *ne_ssl_readable_dname(const ne_ssl_dname *name) { gnutls_x509_dn_t dn; int ret, rdn = 0, flag = 0; ne_buffer *buf; gnutls_x509_ava_st val; #ifdef HAVE_NEW_DN_API dn = name->dn; #else if (name->subject) ret = gnutls_x509_crt_get_subject(name->cert, &dn); else ret = gnutls_x509_crt_get_issuer(name->cert, &dn); if (ret) return ne_strdup(_("[unprintable]")); #endif /* HAVE_NEW_DN_API */ buf = ne_buffer_create(); /* Find the highest rdn... */ while (gnutls_x509_dn_get_rdn_ava(dn, rdn++, 0, &val) == 0) ; /* ..then iterate back to the first: */ while (--rdn >= 0) { int ava = 0; /* Iterate through all AVAs for multivalued AVAs; better than * ne_openssl can do! */ do { ret = gnutls_x509_dn_get_rdn_ava(dn, rdn, ava, &val); /* If the *only* attribute to append is the common name or * email address, use it; otherwise skip those * attributes. */ if (ret == 0 && val.value.size > 0 && ((!CMPOID(&val, OID_emailAddress) && !CMPOID(&val, OID_commonName)) || (buf->used == 1 && rdn == 0))) { flag = 1; if (buf->used > 1) ne_buffer_append(buf, ", ", 2); append_dirstring(buf, &val.value, val.value_tag); } ava++; } while (ret == 0); } return ne_buffer_finish(buf); }
/* Return a malloc-allocated human-readable error string describing * GnuTLS verification error bitmask 'status'; return value must be * freed by the caller. */ static char *verify_error_string(unsigned int status) { ne_buffer *buf = ne_buffer_create(); /* sorry, i18n-ers */ if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { ne_buffer_zappend(buf, _("signed using insecure algorithm")); } else { ne_buffer_snprintf(buf, 64, _("unrecognized errors (%u)"), status); } return ne_buffer_finish(buf); }
char *ne_ssl_readable_dname(const ne_ssl_dname *name) { ne_buffer *buf = ne_buffer_create(); int ret, idx = 0; do { char oid[32] = {0}; size_t oidlen = sizeof oid; ret = name->subject ? gnutls_x509_crt_get_dn_oid(name->cert, idx, oid, &oidlen) : gnutls_x509_crt_get_issuer_dn_oid(name->cert, idx, oid, &oidlen); if (ret == 0) { append_rdn(buf, name->cert, name->subject, oid); idx++; } } while (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); return ne_buffer_finish(buf); }
char *ne_uri_unparse(const ne_uri *uri) { ne_buffer *buf = ne_buffer_create(); if (uri->scheme) { ne_buffer_concat(buf, uri->scheme, ":", NULL); } if (uri->host) { ne_buffer_czappend(buf, "//"); if (uri->userinfo) { ne_buffer_concat(buf, uri->userinfo, "@", NULL); } ne_buffer_zappend(buf, uri->host); if (uri->port > 0 && (!uri->scheme || ne_uri_defaultport(uri->scheme) != uri->port)) { char str[20]; ne_snprintf(str, 20, ":%d", uri->port); ne_buffer_zappend(buf, str); } } ne_buffer_zappend(buf, uri->path); if (uri->query) { ne_buffer_concat(buf, "?", uri->query, NULL); } if (uri->fragment) { ne_buffer_concat(buf, "#", uri->fragment, NULL); } return ne_buffer_finish(buf); }
char *ne_ssl_readable_dname(const ne_ssl_dname *name) { int n, flag = 0; ne_buffer *dump = ne_buffer_create(); const ASN1_OBJECT * const cname = OBJ_nid2obj(NID_commonName), * const email = OBJ_nid2obj(NID_pkcs9_emailAddress); for (n = X509_NAME_entry_count(name->dn); n > 0; n--) { X509_NAME_ENTRY *ent = X509_NAME_get_entry(name->dn, n-1); /* Skip commonName or emailAddress except if there is no other * attribute in dname. */ if ((OBJ_cmp(ent->object, cname) && OBJ_cmp(ent->object, email)) || (!flag && n == 1)) { if (flag++) ne_buffer_append(dump, ", ", 2); if (append_dirstring(dump, ent->value)) ne_buffer_czappend(dump, "???"); } } return ne_buffer_finish(dump); }
/* Return Digest authentication credentials header value for the given * session. */ static char *request_digest(auth_session *sess, struct auth_request *req) { struct ne_md5_ctx a2, rdig; unsigned char a2_md5[16], rdig_md5[16]; char a2_md5_ascii[33], rdig_md5_ascii[33]; char nc_value[9] = {0}; const char *qop_value = "auth"; /* qop-value */ ne_buffer *ret; /* Increase the nonce-count */ if (sess->qop != auth_qop_none) { sess->nonce_count++; ne_snprintf(nc_value, 9, "%08x", sess->nonce_count); NE_DEBUG(NE_DBG_HTTPAUTH, "Nonce count is %u, nc is [%s]\n", sess->nonce_count, nc_value); } /* Calculate H(A2). */ ne_md5_init_ctx(&a2); ne_md5_process_bytes(req->method, strlen(req->method), &a2); ne_md5_process_bytes(":", 1, &a2); ne_md5_process_bytes(req->uri, strlen(req->uri), &a2); ne_md5_finish_ctx(&a2, a2_md5); ne_md5_to_ascii(a2_md5, a2_md5_ascii); NE_DEBUG(NE_DBG_HTTPAUTH, "H(A2): %s\n", a2_md5_ascii); NE_DEBUG(NE_DBG_HTTPAUTH, "Calculating Request-Digest.\n"); /* Now, calculation of the Request-Digest. * The first section is the regardless of qop value * H(A1) ":" unq(nonce-value) ":" */ ne_md5_init_ctx(&rdig); /* Use the calculated H(A1) */ ne_md5_process_bytes(sess->h_a1, 32, &rdig); ne_md5_process_bytes(":", 1, &rdig); ne_md5_process_bytes(sess->nonce, strlen(sess->nonce), &rdig); ne_md5_process_bytes(":", 1, &rdig); if (sess->qop != auth_qop_none) { /* Add on: * nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" */ NE_DEBUG(NE_DBG_HTTPAUTH, "Have qop directive, digesting: [%s:%s:%s]\n", nc_value, sess->cnonce, qop_value); ne_md5_process_bytes(nc_value, 8, &rdig); ne_md5_process_bytes(":", 1, &rdig); ne_md5_process_bytes(sess->cnonce, strlen(sess->cnonce), &rdig); ne_md5_process_bytes(":", 1, &rdig); /* Store a copy of this structure (see note below) */ sess->stored_rdig = rdig; ne_md5_process_bytes(qop_value, strlen(qop_value), &rdig); ne_md5_process_bytes(":", 1, &rdig); } else { /* Store a copy of this structure... we do this because the * calculation of the rspauth= field in the Auth-Info header * is the same as this digest, up to this point. */ sess->stored_rdig = rdig; } /* And finally, H(A2) */ ne_md5_process_bytes(a2_md5_ascii, 32, &rdig); ne_md5_finish_ctx(&rdig, rdig_md5); ne_md5_to_ascii(rdig_md5, rdig_md5_ascii); ret = ne_buffer_create(); ne_buffer_concat(ret, "Digest username=\"", sess->username, "\", " "realm=\"", sess->realm, "\", " "nonce=\"", sess->nonce, "\", " "uri=\"", req->uri, "\", " "response=\"", rdig_md5_ascii, "\", " "algorithm=\"", sess->alg == auth_alg_md5 ? "MD5" : "MD5-sess", "\"", NULL); if (sess->opaque != NULL) { ne_buffer_concat(ret, ", opaque=\"", sess->opaque, "\"", NULL); } if (sess->qop != auth_qop_none) { /* Add in cnonce and nc-value fields */ ne_buffer_concat(ret, ", cnonce=\"", sess->cnonce, "\", " "nc=", nc_value, ", " "qop=\"", qop_value, "\"", NULL); } ne_buffer_zappend(ret, "\r\n"); NE_DEBUG(NE_DBG_HTTPAUTH, "Digest request header is %s\n", ret->data); return ne_buffer_finish(ret); }