/** * infd_acl_account_info_check_password: * @info: A #InfdAclAccountInfo. * @password: The password to check. * * Check whether @password is the correct password to log into account. * * Returns: %TRUE if @password is correct or %FALSE otherwise. */ gboolean infd_acl_account_info_check_password(const InfdAclAccountInfo* info, const gchar* password) { guint password_len; gchar* salted_password; gchar* hash; int res; gchar cmp; guint i; g_return_val_if_fail(info != NULL, FALSE); g_return_val_if_fail(password != NULL, FALSE); password_len = strlen(password); salted_password = g_malloc(32 + password_len); memcpy(salted_password, info->password_salt, 16); memcpy(salted_password + 16, password, password_len); memcpy(salted_password + 16 + password_len, info->password_salt + 16, 16); hash = g_malloc(gnutls_hash_get_len(GNUTLS_DIG_SHA256)); res = gnutls_hash_fast( GNUTLS_DIG_SHA256, salted_password, 32 + password_len, hash ); g_free(salted_password); if(res != GNUTLS_E_SUCCESS) { g_free(hash); return FALSE; } /* length-independent string compare */ cmp = 0; for(i = 0; i < gnutls_hash_get_len(GNUTLS_DIG_SHA256); ++i) cmp |= (info->password_hash[i] ^ hash[i]); g_free(hash); if(cmp != 0) return FALSE; return TRUE; }
void Digest::recycle(bool bin) { unsigned size = bufsize; if(!context || hashid == 0) return; if(!bufsize) { gnutls_hash_deinit((MD_CTX)context, buffer); context = NULL; gnutls_hash_init((MD_CTX *)&context, (MD_ID)hashid); } else Digest::reset(); size = gnutls_hash_get_len((MD_ID)hashid); if(!size || !context || !hashid) return; if(bin) gnutls_hash((MD_CTX)context, buffer, size); else { unsigned count = 0; while(count < size) { snprintf(textbuf + (count * 2), 3, "%2.2x", buffer[count]); ++count; } gnutls_hash((MD_CTX)context, textbuf, size * 2); } bufsize = 0; }
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg, const struct iovec *iov, size_t niov, uint8_t **result, size_t *resultlen, Error **errp) { int i, ret; gnutls_hash_hd_t dig; if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map)) { error_setg(errp, "Unknown hash algorithm %d", alg); return -1; } ret = gnutls_hash_init(&dig, qcrypto_hash_alg_map[alg]); if (ret < 0) { error_setg(errp, "Unable to initialize hash algorithm: %s", gnutls_strerror(ret)); return -1; } for (i = 0; i < niov; i++) { ret = gnutls_hash(dig, iov[i].iov_base, iov[i].iov_len); if (ret < 0) { error_setg(errp, "Unable process hash data: %s", gnutls_strerror(ret)); goto error; } } ret = gnutls_hash_get_len(qcrypto_hash_alg_map[alg]); if (ret <= 0) { error_setg(errp, "Unable to get hash length: %s", gnutls_strerror(ret)); goto error; } if (*resultlen == 0) { *resultlen = ret; *result = g_new0(uint8_t, *resultlen); } else if (*resultlen != ret) { error_setg(errp, "Result buffer size %zu is smaller than hash %d", *resultlen, ret); goto error; } gnutls_hash_deinit(dig, *result); return 0; error: gnutls_hash_deinit(dig, NULL); return -1; }
bool Digest::has(const char *type) { MD_ID id = (MD_ID)__context::map_digest(type); if(!id || (gnutls_hash_get_len(id) < 1)) return false; return true; }
Vector<uint8_t> CryptoDigest::computeHash() { Vector<uint8_t> result; int digestLen = gnutls_hash_get_len(m_context->algorithm); result.resize(digestLen); gnutls_hash_output(m_context->hash, result.data()); return result; }
void Cipher::Key::assign(const char *text, size_t size, const unsigned char *salt, unsigned count) { if(!hashid || !algoid) { keysize = 0; return; } size_t kpos = 0, ivpos = 0; size_t mdlen = gnutls_hash_get_len((MD_ID)hashid); size_t tlen = strlen(text); if(!hashid || !mdlen) { clear(); return; } char previous[MAX_DIGEST_HASHSIZE / 8]; unsigned char temp[MAX_DIGEST_HASHSIZE / 8]; MD_CTX mdc; unsigned prior = 0; unsigned loop; if(!salt) salt = _salt; if(!count) count = _rounds; do { gnutls_hash_init(&mdc, (MD_ID)hashid); if(prior++) gnutls_hash(mdc, previous, mdlen); gnutls_hash(mdc, text, tlen); if(salt) gnutls_hash(mdc, salt, 8); gnutls_hash_deinit(mdc, previous); for(loop = 1; loop < count; ++loop) { memcpy(temp, previous, mdlen); gnutls_hash_fast((MD_ID)hashid, temp, mdlen, previous); } size_t pos = 0; while(kpos < keysize && pos < mdlen) keybuf[kpos++] = previous[pos++]; while(ivpos < blksize && pos < mdlen) ivbuf[ivpos++] = previous[pos++]; } while(kpos < keysize || ivpos < blksize); }
void Digest::set(const char *type) { secure::init(); release(); hashid = __context::map_digest(type); if(!hashid || gnutls_hash_get_len((MD_ID)hashid) < 1) { hashid = 0; return; } gnutls_hash_init((MD_CTX *)&context, (MD_ID)hashid); }
const unsigned char *Digest::get(void) { unsigned count = 0; unsigned size = 0; if(bufsize) return buffer; if(!context || hashid == 0) return NULL; gnutls_hash_deinit((MD_CTX)context, buffer); size = gnutls_hash_get_len((MD_ID)hashid); context = NULL; bufsize = size; while(count < bufsize) { snprintf(textbuf + (count * 2), 3, "%2.2x", buffer[count]); ++count; } return buffer; }
static int get_entry(liServer *srv, ocsp_response_cert_entry* entry, gnutls_ocsp_resp_t resp, unsigned int ndx) { int r; memset(entry, 0, sizeof(*entry)); r = gnutls_ocsp_resp_get_single( resp, ndx, &entry->digest, &entry->issuer_name_hash, NULL, &entry->serial, NULL, NULL, NULL, NULL, NULL); if (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE == r) return r; if (GNUTLS_E_SUCCESS > r) { ERROR(srv, "Couldn't retrieve OCSP response information for entry %u (%s): %s", ndx, gnutls_strerror_name(r), gnutls_strerror(r)); return r; } if (0 == entry->serial.size || GNUTLS_DIG_UNKNOWN == entry->digest || entry->issuer_name_hash.size != gnutls_hash_get_len(entry->digest)) { ERROR(srv, "Invalid OCSP response data in entry %u", ndx); return GNUTLS_E_OCSP_RESPONSE_ERROR; } return GNUTLS_E_SUCCESS; }
ssize_t /* O - Size of hash or -1 on error */ cupsHashData(const char *algorithm, /* I - Algorithm name */ const void *data, /* I - Data to hash */ size_t datalen, /* I - Length of data to hash */ unsigned char *hash, /* I - Hash buffer */ size_t hashsize) /* I - Size of hash buffer */ { if (!algorithm || !data || datalen == 0 || !hash || hashsize == 0) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad arguments to function"), 1); return (-1); } #ifdef __APPLE__ if (!strcmp(algorithm, "sha")) { /* * SHA-1... */ CC_SHA1_CTX ctx; /* SHA-1 context */ if (hashsize < CC_SHA1_DIGEST_LENGTH) goto too_small; CC_SHA1_Init(&ctx); CC_SHA1_Update(&ctx, data, (CC_LONG)datalen); CC_SHA1_Final(hash, &ctx); return (CC_SHA1_DIGEST_LENGTH); } else if (!strcmp(algorithm, "sha2-224")) { CC_SHA256_CTX ctx; /* SHA-224 context */ if (hashsize < CC_SHA224_DIGEST_LENGTH) goto too_small; CC_SHA224_Init(&ctx); CC_SHA224_Update(&ctx, data, (CC_LONG)datalen); CC_SHA224_Final(hash, &ctx); return (CC_SHA224_DIGEST_LENGTH); } else if (!strcmp(algorithm, "sha2-256")) { CC_SHA256_CTX ctx; /* SHA-256 context */ if (hashsize < CC_SHA256_DIGEST_LENGTH) goto too_small; CC_SHA256_Init(&ctx); CC_SHA256_Update(&ctx, data, (CC_LONG)datalen); CC_SHA256_Final(hash, &ctx); return (CC_SHA256_DIGEST_LENGTH); } else if (!strcmp(algorithm, "sha2-384")) { CC_SHA512_CTX ctx; /* SHA-384 context */ if (hashsize < CC_SHA384_DIGEST_LENGTH) goto too_small; CC_SHA384_Init(&ctx); CC_SHA384_Update(&ctx, data, (CC_LONG)datalen); CC_SHA384_Final(hash, &ctx); return (CC_SHA384_DIGEST_LENGTH); } else if (!strcmp(algorithm, "sha2-512")) { CC_SHA512_CTX ctx; /* SHA-512 context */ if (hashsize < CC_SHA512_DIGEST_LENGTH) goto too_small; CC_SHA512_Init(&ctx); CC_SHA512_Update(&ctx, data, (CC_LONG)datalen); CC_SHA512_Final(hash, &ctx); return (CC_SHA512_DIGEST_LENGTH); } else if (!strcmp(algorithm, "sha2-512_224")) { CC_SHA512_CTX ctx; /* SHA-512 context */ unsigned char temp[CC_SHA512_DIGEST_LENGTH]; /* SHA-512 hash */ /* * SHA2-512 truncated to 224 bits (28 bytes)... */ if (hashsize < CC_SHA224_DIGEST_LENGTH) goto too_small; CC_SHA512_Init(&ctx); CC_SHA512_Update(&ctx, data, (CC_LONG)datalen); CC_SHA512_Final(temp, &ctx); memcpy(hash, temp, CC_SHA224_DIGEST_LENGTH); return (CC_SHA224_DIGEST_LENGTH); } else if (!strcmp(algorithm, "sha2-512_256")) { CC_SHA512_CTX ctx; /* SHA-512 context */ unsigned char temp[CC_SHA512_DIGEST_LENGTH]; /* SHA-512 hash */ /* * SHA2-512 truncated to 256 bits (32 bytes)... */ if (hashsize < CC_SHA256_DIGEST_LENGTH) goto too_small; CC_SHA512_Init(&ctx); CC_SHA512_Update(&ctx, data, (CC_LONG)datalen); CC_SHA512_Final(temp, &ctx); memcpy(hash, temp, CC_SHA256_DIGEST_LENGTH); return (CC_SHA256_DIGEST_LENGTH); } #elif defined(HAVE_GNUTLS) gnutls_digest_algorithm_t alg = GNUTLS_DIG_UNKNOWN; /* Algorithm */ unsigned char temp[64]; /* Temporary hash buffer */ size_t tempsize = 0; /* Truncate to this size? */ if (!strcmp(algorithm, "sha")) alg = GNUTLS_DIG_SHA1; else if (!strcmp(algorithm, "sha2-224")) alg = GNUTLS_DIG_SHA224; else if (!strcmp(algorithm, "sha2-256")) alg = GNUTLS_DIG_SHA256; else if (!strcmp(algorithm, "sha2-384")) alg = GNUTLS_DIG_SHA384; else if (!strcmp(algorithm, "sha2-512")) alg = GNUTLS_DIG_SHA512; else if (!strcmp(algorithm, "sha2-512_224")) { alg = GNUTLS_DIG_SHA512; tempsize = 28; } else if (!strcmp(algorithm, "sha2-512_256")) { alg = GNUTLS_DIG_SHA512; tempsize = 32; } if (alg != GNUTLS_DIG_UNKNOWN) { if (tempsize > 0) { /* * Truncate result to tempsize bytes... */ if (hashsize < tempsize) goto too_small; gnutls_hash_fast(alg, data, datalen, temp); memcpy(hash, temp, tempsize); return ((ssize_t)tempsize); } if (hashsize < gnutls_hash_get_len(alg)) goto too_small; gnutls_hash_fast(alg, data, datalen, hash); return (gnutls_hash_get_len(alg)); } #else /* * No hash support without CommonCrypto or GNU TLS... */ if (hashsize < 64) goto too_small; #endif /* __APPLE__ */ /* * Unknown hash algorithm... */ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown hash algorithm."), 1); return (-1); /* * We get here if the buffer is too small. */ too_small: _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1); return (-1); }
static void dane_info(const char *host, const char *proto, unsigned int port, unsigned int ca, unsigned int domain, common_info_st * cinfo) { gnutls_pubkey_t pubkey; gnutls_x509_crt_t crt; unsigned char digest[64]; gnutls_datum_t t; int ret; unsigned int usage, selector, type; size_t size; if (proto == NULL) proto = "tcp"; if (port == 0) port = 443; crt = load_cert(0, cinfo); if (crt != NULL && HAVE_OPT(X509)) { selector = 0; /* X.509 */ size = lbuffer_size; ret = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, lbuffer, &size); if (ret < 0) { fprintf(stderr, "export error: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); } else { /* use public key only */ selector = 1; ret = gnutls_pubkey_init(&pubkey); if (ret < 0) { fprintf(stderr, "pubkey_init: %s\n", gnutls_strerror(ret)); exit(1); } if (crt != NULL) { ret = gnutls_pubkey_import_x509(pubkey, crt, 0); if (ret < 0) { fprintf(stderr, "pubkey_import_x509: %s\n", gnutls_strerror(ret)); exit(1); } size = lbuffer_size; ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, lbuffer, &size); if (ret < 0) { fprintf(stderr, "pubkey_export: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); } else { pubkey = load_pubkey(1, cinfo); size = lbuffer_size; ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, lbuffer, &size); if (ret < 0) { fprintf(stderr, "export error: %s\n", gnutls_strerror(ret)); exit(1); } } gnutls_pubkey_deinit(pubkey); } if (default_dig != GNUTLS_DIG_SHA256 && default_dig != GNUTLS_DIG_SHA512) { if (default_dig != GNUTLS_DIG_UNKNOWN) fprintf(stderr, "Unsupported digest. Assuming SHA256.\n"); default_dig = GNUTLS_DIG_SHA256; } ret = gnutls_hash_fast(default_dig, lbuffer, size, digest); if (ret < 0) { fprintf(stderr, "hash error: %s\n", gnutls_strerror(ret)); exit(1); } if (default_dig == GNUTLS_DIG_SHA256) type = 1; else type = 2; /* DANE certificate classification crap */ if (domain == 0) { if (ca) usage = 0; else usage = 1; } else { if (ca) usage = 2; else usage = 3; } t.data = digest; t.size = gnutls_hash_get_len(default_dig); size = lbuffer_size; ret = gnutls_hex_encode(&t, (void *) lbuffer, &size); if (ret < 0) { fprintf(stderr, "hex encode error: %s\n", gnutls_strerror(ret)); exit(1); } fprintf(outfile, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port, proto, host, usage, selector, type, lbuffer); }
static gboolean ssl_verify_certificate (LmSSL *ssl, const gchar *server) { LmSSLBase *base; unsigned int status; int rc; base = LM_SSL_BASE (ssl); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ rc = gnutls_certificate_verify_peers2 (ssl->gnutls_session, &status); if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (rc != 0) { if (base->func (ssl, LM_SSL_STATUS_GENERIC_ERROR, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (status & GNUTLS_CERT_INVALID || status & GNUTLS_CERT_REVOKED) { if (base->func (ssl, LM_SSL_STATUS_UNTRUSTED_CERT, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_expiration_time_peers (ssl->gnutls_session) < time (0)) { if (base->func (ssl, LM_SSL_STATUS_CERT_EXPIRED, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_activation_time_peers (ssl->gnutls_session) > time (0)) { if (base->func (ssl, LM_SSL_STATUS_CERT_NOT_ACTIVATED, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_type_get (ssl->gnutls_session) == GNUTLS_CRT_X509) { const gnutls_datum_t* cert_list; guint cert_list_size; gnutls_digest_algorithm_t digest = GNUTLS_DIG_SHA256; guchar digest_bin[LM_FINGERPRINT_LENGTH]; size_t digest_size; gnutls_x509_crt_t cert; cert_list = gnutls_certificate_get_peers (ssl->gnutls_session, &cert_list_size); if (cert_list == NULL) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } gnutls_x509_crt_init (&cert); if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) != 0) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (!gnutls_x509_crt_check_hostname (cert, server)) { if (base->func (ssl, LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } gnutls_x509_crt_deinit (cert); digest_size = gnutls_hash_get_len(digest); g_assert(digest_size < sizeof(digest_bin)); if (gnutls_fingerprint (digest, &cert_list[0], digest_bin, &digest_size) >= 0) { _lm_ssl_base_set_fingerprint(base, digest_bin, digest_size); if (_lm_ssl_base_check_fingerprint(base) != 0 && base->func (ssl, LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } else if (base->func (ssl, LM_SSL_STATUS_GENERIC_ERROR, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } return TRUE; }
/** * infd_acl_account_info_to_xml: * @info: A #InfdAclAccountInfo. * @xml: XML node to write the account information to. * * Serializes a #InfdAclAccountInfo object into an XML node. The account * information can be deserialized again with * infd_acl_account_info_from_xml(). */ void infd_acl_account_info_to_xml(const InfdAclAccountInfo* info, xmlNodePtr xml) { guint i; gnutls_datum_t datum; size_t out_size; gchar* out; int res; g_return_if_fail(info != NULL); g_return_if_fail(xml != NULL); inf_acl_account_to_xml(&info->account, xml); for(i = 0; i < info->n_certificates; ++i) { xmlNewChild( xml, NULL, (const xmlChar*)"certificate", (const xmlChar*)info->certificates[i] ); } if(info->password_salt != NULL) { datum.data = info->password_salt; datum.size = 32; res = gnutls_hex_encode(&datum, NULL, &out_size); g_assert(res == GNUTLS_E_SHORT_MEMORY_BUFFER); out = g_malloc(out_size + 1); res = gnutls_hex_encode(&datum, out, &out_size); g_assert(res == GNUTLS_E_SUCCESS); out[out_size] = '\0'; inf_xml_util_set_attribute(xml, "password-salt", out); g_free(out); } if(info->password_hash != NULL) { datum.data = info->password_hash; datum.size = gnutls_hash_get_len(GNUTLS_DIG_SHA256); res = gnutls_hex_encode(&datum, NULL, &out_size); g_assert(res == GNUTLS_E_SHORT_MEMORY_BUFFER); out = g_malloc(out_size + 1); res = gnutls_hex_encode(&datum, out, &out_size); g_assert(res == GNUTLS_E_SUCCESS); out[out_size] = '\0'; inf_xml_util_set_attribute(xml, "password-hash", out); g_free(out); } if(info->first_seen != 0) { inf_xml_util_set_attribute_double( xml, "first-seen", info->first_seen / 1e6 ); } if(info->last_seen != 0) { inf_xml_util_set_attribute_double( xml, "last-seen", info->last_seen / 1e6 ); } }
/** * infd_acl_account_info_from_xml: * @xml: The XML node from which to read the account information. * @error: Location to store error information, if any. * * Reads information for one account from a serialized XML node. The account * info can be written to XML with the infd_acl_account_info_to_xml() * function. If the function fails it returns %NULL and @error is set. * * Returns: A #InfdAclAccountInfo, or %NULL. Free with * infd_acl_account_info_free() when no longer needed. */ InfdAclAccountInfo* infd_acl_account_info_from_xml(xmlNodePtr xml, GError** error) { InfdAclAccountInfo* info; InfAclAccount* account; GError* local_error; gboolean has_first_seen; gdouble first_seen; gboolean has_last_seen; gdouble last_seen; xmlChar* password_salt; xmlChar* password_hash; gnutls_datum_t datum; size_t hash_len; int res; gchar* binary_salt; gchar* binary_hash; xmlNodePtr child; GPtrArray* certificate_array; guint i; g_return_val_if_fail(xml != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); local_error = NULL; has_first_seen = inf_xml_util_get_attribute_double( xml, "first-seen", &first_seen, &local_error ); if(local_error != NULL) return NULL; has_last_seen = inf_xml_util_get_attribute_double( xml, "last-seen", &last_seen, &local_error ); if(local_error != NULL) return NULL; account = inf_acl_account_from_xml(xml, error); if(account == NULL) return NULL; password_salt = inf_xml_util_get_attribute(xml, "password-salt"); password_hash = inf_xml_util_get_attribute(xml, "password-hash"); if( (password_salt != NULL && password_hash == NULL) || (password_salt == NULL && password_hash != NULL)) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, "%s", _("If one of \"password-hash\" or \"password-salt\" is provided, the " "other must be provided as well.") ); if(password_salt != NULL) xmlFree(password_salt); if(password_hash != NULL) xmlFree(password_hash); inf_acl_account_free(account); return NULL; } if(password_salt != NULL && password_hash != NULL) { datum.data = password_salt; datum.size = strlen(password_salt); hash_len = 32; binary_salt = g_malloc(hash_len); res = gnutls_hex_decode(&datum, binary_salt, &hash_len); xmlFree(password_salt); if(hash_len != 32) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, "%s", _("The length of the password salt is incorrect, it should " "be 32 bytes") ); xmlFree(password_hash); g_free(binary_salt); return NULL; } else if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); xmlFree(password_hash); g_free(binary_salt); return NULL; } datum.data = password_hash; datum.size = strlen(password_hash); hash_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256); binary_hash = g_malloc(hash_len); res = gnutls_hex_decode(&datum, binary_hash, &hash_len); xmlFree(password_hash); if(hash_len != gnutls_hash_get_len(GNUTLS_DIG_SHA256)) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, _("The length of the password hash is incorrect, it should be " "%u bytes"), (unsigned int)gnutls_hash_get_len(GNUTLS_DIG_SHA256) ); g_free(binary_salt); g_free(binary_hash); return NULL; } else if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); g_free(binary_salt); g_free(binary_hash); return NULL; } } else { binary_salt = NULL; binary_hash = NULL;\ if(password_salt != NULL) xmlFree(password_salt); if(password_hash != NULL) xmlFree(password_hash); } certificate_array = g_ptr_array_new(); for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "certificate") == 0) g_ptr_array_add(certificate_array, xmlNodeGetContent(child)); } info = infd_acl_account_info_new(account->id, account->name, FALSE); inf_acl_account_free(account); info->certificates = g_malloc(sizeof(gchar*) * certificate_array->len); for(i = 0; i < certificate_array->len; ++i) { info->certificates[i] = g_strdup(certificate_array->pdata[i]); xmlFree(certificate_array->pdata[i]); } info->n_certificates = certificate_array->len; g_ptr_array_free(certificate_array, TRUE); info->password_salt = binary_salt; info->password_hash = binary_hash; if(has_first_seen == TRUE) info->first_seen = first_seen * 1e6; else info->first_seen = 0; if(has_last_seen == TRUE) info->last_seen = last_seen * 1e6; else info->last_seen = 0; return info; }
/** * infd_acl_account_info_set_password: * @info: A #InfdAclAccountInfo. * @password: The new password for the account, or %NULL. * @error: Location to store error information, if any. * * Changes the password for the given account. If @password is %NULL the * password is unset, which means that it is not possible to log into this * account with password authentication. * * If @password is non-%NULL, a new random salt is generated and a SHA256 * hash of the salt and the password is stored. * * If an error occurs while changing the password the functions set @error * and returns %FALSE. * * Returns: %TRUE in case of success or %FALSE otherwise. */ gboolean infd_acl_account_info_set_password(InfdAclAccountInfo* info, const gchar* password, GError** error) { gchar* new_salt; gchar* new_hash; gchar* salted_password; guint password_len; int res; g_return_val_if_fail(info != NULL, FALSE); if(password == NULL) { g_free(info->password_salt); g_free(info->password_hash); info->password_salt = NULL; info->password_hash = NULL; } else { new_salt = g_malloc(32); res = gnutls_rnd(GNUTLS_RND_RANDOM, new_salt, 32); if(res != GNUTLS_E_SUCCESS) { g_free(new_salt); inf_gnutls_set_error(error, res); return FALSE; } password_len = strlen(password); salted_password = g_malloc(32 + password_len); memcpy(salted_password, new_salt, 16); memcpy(salted_password + 16, password, password_len); memcpy(salted_password + 16 + password_len, new_salt + 16, 16); new_hash = g_malloc(gnutls_hash_get_len(GNUTLS_DIG_SHA256)); res = gnutls_hash_fast( GNUTLS_DIG_SHA256, salted_password, 32 + password_len, new_hash ); g_free(salted_password); if(res != GNUTLS_E_SUCCESS) { g_free(new_hash); g_free(new_salt); inf_gnutls_set_error(error, res); return FALSE; } g_free(info->password_salt); g_free(info->password_hash); info->password_salt = new_salt; info->password_hash = new_hash; } return TRUE; }
static void DoExtFileHashing_FD(tBuffer *bIn, tBuffer *bOut, u_int32_t id, int fd) { gnutls_digest_algorithm_t gnuTlsAlgo = GNUTLS_DIG_UNKNOWN; u_int64_t offset, length; u_int32_t blockSize; char *algo; algo = BufferGetString(bIn); offset = BufferGetInt64(bIn); length = BufferGetInt64(bIn); blockSize = BufferGetInt32(bIn); if (lseek(fd, offset, SEEK_SET) == -1) { SendStatus(bOut, id, errnoToPortable(errno)); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error lseek1")); goto endOfFileHashing; } if (length == 0)//read the file to the end { u_int64_t endOfFile; if ((endOfFile = lseek(fd, 0, SEEK_END)) == -1) { SendStatus(bOut, id, errnoToPortable(errno)); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error lseek2")); goto endOfFileHashing; } length = endOfFile - offset; if (lseek(fd, offset, SEEK_SET) == -1) { SendStatus(bOut, id, errnoToPortable(errno)); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error lseek3")); goto endOfFileHashing; } } if (blockSize == 0)//read length in one time blockSize = length; DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Algo:%s Fd:%i Offset:%llu Length:%llu BlockSize:%i", algo, fd, offset, length, blockSize)); if (strcasecmp("md2", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_MD2; else if (strcasecmp("md5", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_MD5; else if (strcasecmp("sha1", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA1; else if (strcasecmp("sha224", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA224; else if (strcasecmp("sha256", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA256; else if (strcasecmp("sha384", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA384; else if (strcasecmp("sha512", algo) == 0) gnuTlsAlgo = GNUTLS_DIG_SHA512; if (gnuTlsAlgo != GNUTLS_DIG_UNKNOWN) { gnutls_hash_hd_t dig; tBuffer *b; size_t keySize = gnutls_hash_get_len(gnuTlsAlgo); char *gnuKey; char data[SSH2_READ_HASH]; int inError = 0; int gnulTlsError; b = BufferNew(); BufferPutInt8FAST(b, SSH2_FXP_EXTENDED_REPLY); BufferPutInt32(b, id); BufferPutString(b, algo); gnuKey = calloc(1, keySize); if (gnuKey == NULL) goto endOfFileHashing; if ((gnulTlsError = gnutls_hash_init(&dig, gnuTlsAlgo)) == 0) { while (length > 0) { u_int32_t r, off, len; length = (length > (u_int64_t) blockSize) ? length - (u_int64_t) blockSize : 0; off = blockSize; len = sizeof(data); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Read:%i Rest:%llu", len, length)); while ((r = read(fd, data, len)) > 0) { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Compute block (%u/%u %u)", len, r, off)); if ((gnulTlsError = gnutls_hash(dig, data, r)) != 0) { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error gnutls_hmac [error: %i]", gnulTlsError)); inError = 1; break; } off -= r; if (off < sizeof(data)) len = off; if (off == 0) break; } } } else { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Error gnutls_hash_init [keySize: %li] [error: %i]", keySize, gnulTlsError)); inError = 1; } if (inError == 0) { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Compute key... [keySize: %li][keyPointer: %p]", keySize, gnuKey)); gnutls_hash_deinit(dig, gnuKey); DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]Hash: %X%X%X ...", gnuKey[0], gnuKey[1], gnuKey[2])); BufferPutRawData(b, gnuKey, keySize); BufferPutPacket(bOut, b); } else SendStatus(bOut, id, SSH2_FX_FAILURE); BufferDelete(b); free(gnuKey); } else { DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]No algorithm: %s", algo)); SendStatus(bOut, id, SSH2_FX_OP_UNSUPPORTED); } endOfFileHashing: DEBUG((MYLOG_DEBUG, "[DoExtFileHashing_FD]End")); free(algo); }
gboolean crypto_md5_hash (const char *salt, const gsize salt_len, const char *password, gsize password_len, char *buffer, gsize buflen, GError **error) { gnutls_hash_hd_t ctx; int err; int nkey = buflen; const gsize digest_len = 16; int count = 0; char digest[MD5_HASH_LEN]; char *p = buffer; if (salt) g_return_val_if_fail (salt_len >= SALT_LEN, FALSE); g_return_val_if_fail (password != NULL, FALSE); g_return_val_if_fail (password_len > 0, FALSE); g_return_val_if_fail (buffer != NULL, FALSE); g_return_val_if_fail (buflen > 0, FALSE); if (gnutls_hash_get_len (GNUTLS_DIG_MD5) > MD5_HASH_LEN) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_MD5_INIT_FAILED, _("Hash length too long (%d > %d)."), gnutls_hash_get_len (GNUTLS_DIG_MD5), MD5_HASH_LEN); return FALSE; } while (nkey > 0) { int i = 0; err = gnutls_hash_init (&ctx, GNUTLS_DIG_MD5); if (err < 0) goto error; if (count++) gnutls_hash (ctx, digest, digest_len); gnutls_hash (ctx, password, password_len); if (salt) gnutls_hash (ctx, salt, SALT_LEN); /* Only use 8 bytes of salt */ gnutls_hash_deinit (ctx, digest); while (nkey && (i < digest_len)) { *(p++) = digest[i++]; nkey--; } } memset (digest, 0, sizeof (digest)); return TRUE; error: memset (digest, 0, sizeof (digest)); g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_MD5_INIT_FAILED, _("Failed to initialize the MD5 engine: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); return FALSE; }