/* * Create a bkrp_encrypted_secret_vX structure * the version depends on the version parameter * the structure is returned as a blob. * The broken flag is to indicate if we want * to create a non conform to specification structre */ static DATA_BLOB *create_unencryptedsecret(TALLOC_CTX *mem_ctx, bool broken, int version) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); DATA_BLOB *blob = talloc_zero(mem_ctx, DATA_BLOB); enum ndr_err_code ndr_err; if (version == 2) { struct bkrp_encrypted_secret_v2 unenc_sec; ZERO_STRUCT(unenc_sec); unenc_sec.secret_len = sizeof(secret); unenc_sec.secret = discard_const_p(uint8_t, secret); generate_random_buffer(unenc_sec.payload_key, sizeof(unenc_sec.payload_key)); ndr_err = ndr_push_struct_blob(blob, blob, &unenc_sec, (ndr_push_flags_fn_t)ndr_push_bkrp_encrypted_secret_v2); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NULL; } if (broken) { /* The magic value is correctly set by the NDR push * but we want to test the behavior of the server * if a differrent value is provided */ ((uint8_t*)blob->data)[4] = 79; /* A great year !!! */ } } if (version == 3) { struct bkrp_encrypted_secret_v3 unenc_sec; ZERO_STRUCT(unenc_sec); unenc_sec.secret_len = sizeof(secret); unenc_sec.secret = discard_const_p(uint8_t, secret); generate_random_buffer(unenc_sec.payload_key, sizeof(unenc_sec.payload_key)); ndr_err = ndr_push_struct_blob(blob, blob, &unenc_sec, (ndr_push_flags_fn_t)ndr_push_bkrp_encrypted_secret_v3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NULL; } if (broken) { /* * The magic value is correctly set by the NDR push * but we want to test the behavior of the server * if a differrent value is provided */ ((uint8_t*)blob->data)[4] = 79; /* A great year !!! */ } } talloc_free(tmp_ctx); return blob; }
static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLOB *names_blob) { uint8_t client_chal[8]; DATA_BLOB response = data_blob(NULL, 0); uint8_t long_date[8]; NTTIME nttime; unix_to_nt_time(&nttime, time(NULL)); generate_random_buffer(client_chal, sizeof(client_chal)); push_nttime(long_date, 0, nttime); /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */ /* Deliberately ignore return here.. */ (void)msrpc_gen(mem_ctx, &response, "ddbbdb", 0x00000101, /* Header */ 0, /* 'Reserved' */ long_date, 8, /* Timestamp */ client_chal, 8, /* client challenge */ 0, /* Unknown */ names_blob->data, names_blob->length); /* End of name list */ return response; }
BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode) { int new_pw_len = strlen(passwd) * (unicode ? 2 : 1); if (new_pw_len > 512) { DEBUG(0,("make_oem_passwd_hash: new password is too long.\n")); return False; } /* * Now setup the data area. * We need to generate a random fill * for this area to make it harder to * decrypt. JRA. */ generate_random_buffer((unsigned char *)data, 516, False); if (unicode) { struni2( &data[512 - new_pw_len], passwd); } else { fstrcpy( &data[512 - new_pw_len], passwd); } SIVAL(data, 512, new_pw_len); #ifdef DEBUG_PASSWORD DEBUG(100,("make_oem_passwd_hash\n")); dump_data(100, data, 516); #endif SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True); return True; }
/** * open up the randseed database and set the random number generator callback */ bool randseed_init(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx) { char *fname; uint8_t dummy; struct tdb_wrap *tdb; fname = lpcfg_private_path(mem_ctx, lp_ctx, "randseed.tdb"); tdb = tdb_wrap_open(mem_ctx, fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); if (!tdb) { DEBUG(0,("Failed to open %s\n", fname)); talloc_free(fname); return false; } talloc_free(fname); /** * Set a reseed function for the crypto random generator * * This avoids a problem where systems without /dev/urandom * could send the same challenge to multiple clients */ set_rand_reseed_callback((void (*) (void *, int *))get_rand_seed, tdb); /* Ensure that the reseed is done now, while we are root, etc */ generate_random_buffer(&dummy, sizeof(dummy)); return true; }
static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx, const uint8_t ntlm_v2_hash[16], const DATA_BLOB *server_chal) { uint8_t lmv2_response[16]; DATA_BLOB lmv2_client_data = data_blob_talloc(mem_ctx, NULL, 8); DATA_BLOB final_response = data_blob_talloc(mem_ctx, NULL,24); /* LMv2 */ /* client-supplied random data */ generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length); /* Given that data, and the challenge from the server, generate a response */ SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response); memcpy(final_response.data, lmv2_response, sizeof(lmv2_response)); /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */ memcpy(final_response.data+sizeof(lmv2_response), lmv2_client_data.data, lmv2_client_data.length); data_blob_free(&lmv2_client_data); return final_response; }
/*********************************************************** encode a password buffer with a unicode password. The buffer is filled with random data to make it harder to attack. ************************************************************/ bool encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flags) { uint8_t new_pw[512]; ssize_t new_pw_len; /* the incoming buffer can be any alignment. */ string_flags |= STR_NOALIGN; new_pw_len = push_string(new_pw, password, sizeof(new_pw), string_flags); if (new_pw_len == -1) { return false; } memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len); generate_random_buffer(buffer, 512 - new_pw_len); /* * The length of the new password is in the last 4 bytes of * the data buffer. */ SIVAL(buffer, 512, new_pw_len); ZERO_STRUCT(new_pw); return true; }
static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state) { static uchar chal[8]; generate_random_buffer(chal, sizeof(chal)); return chal; }
/** * generate a random GUID */ struct GUID GUID_random(void) { struct GUID guid; generate_random_buffer((uint8_t *)&guid, sizeof(guid)); guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80; guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000; return guid; }
static PyObject *py_auth_smbd(PyObject *self, PyObject *args, PyObject *kw) { static char *kwlist[] = {"username", "password", "use_lm_hash", "use_nt_hash", NULL }; struct winbindd_request request; struct winbindd_response response; char *username, *password; int use_lm_hash = 1, use_nt_hash = 1; if (!PyArg_ParseTupleAndKeywords( args, kw, "ss|ii", kwlist, &username, &password, &use_lm_hash, &use_nt_hash)) return NULL; ZERO_STRUCT(request); ZERO_STRUCT(response); if (push_utf8_fstring(request.data.auth_crap.user, username) == -1) { PyErr_SetString("unable to create utf8 string"); return NULL; } generate_random_buffer(request.data.smbd_auth_crap.chal, 8); if (use_lm_hash) { SMBencrypt((uchar *)password, request.data.smbd_auth_crap.chal, (uchar *)request.data.smbd_auth_crap.lm_resp); request.data.smbd_auth_crap.lm_resp_len = 24; } if (use_nt_hash) { SMBNTencrypt((uchar *)password, request.data.smbd_auth_crap.chal, (uchar *)request.data.smbd_auth_crap.nt_resp); request.data.smbd_auth_crap.nt_resp_len = 24; } if (!secrets_fetch_trust_account_password( lp_workgroup(), request.data.smbd_auth_crap.proof, NULL)) { PyErr_SetString( winbind_error, "unable to fetch domain secret"); return NULL; } if (winbindd_request(WINBINDD_SMBD_AUTH_CRAP, &request, &response) != NSS_STATUS_SUCCESS) { PyErr_SetString(winbind_error, "lookup failed"); return NULL; } return PyInt_FromLong(response.data.auth.nt_status); }
uint64_t serverid_get_random_unique_id(void) { uint64_t unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY; while (unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) { generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id)); } return unique_id; }
DATA_BLOB get_challenge(void) { static DATA_BLOB chal; if (opt_challenge.length) return opt_challenge; chal = data_blob(NULL, 8); generate_random_buffer(chal.data, chal.length); return chal; }
void smb_uuid_generate_random(GUID *out) { GUID tmp; struct uuid uu; generate_random_buffer(tmp.info, sizeof(tmp.info), True); uuid_unpack(tmp, &uu); uu.clock_seq[0] = (uu.clock_seq[0] & 0x3F) | 0x80; uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; uuid_pack(&uu, out); }
static NTSTATUS libnet_SetPassword_samr_handle_25(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r) { NTSTATUS status; struct samr_SetUserInfo2 sui; union samr_UserInfo u_info; DATA_BLOB session_key; DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); uint8_t confounder[16]; struct MD5Context md5; if (!r->samr_handle.in.info21) { return NT_STATUS_INVALID_PARAMETER_MIX; } /* prepare samr_SetUserInfo2 level 25 */ ZERO_STRUCT(u_info); u_info.info25.info = *r->samr_handle.in.info21; u_info.info25.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT; encode_pw_buffer(u_info.info25.password.data, r->samr_handle.in.newpassword, STR_UNICODE); status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key); if (!NT_STATUS_IS_OK(status)) { r->samr_handle.out.error_string = talloc_asprintf(mem_ctx, "dcerpc_fetch_session_key failed: %s", nt_errstr(status)); return status; } generate_random_buffer((uint8_t *)confounder, 16); MD5Init(&md5); MD5Update(&md5, confounder, 16); MD5Update(&md5, session_key.data, session_key.length); MD5Final(confounded_session_key.data, &md5); arcfour_crypt_blob(u_info.info25.password.data, 516, &confounded_session_key); memcpy(&u_info.info25.password.data[516], confounder, 16); sui.in.user_handle = r->samr_handle.in.user_handle; sui.in.info = &u_info; sui.in.level = 25; /* 8. try samr_SetUserInfo2 level 25 to set the password */ status = dcerpc_samr_SetUserInfo2(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui); if (!NT_STATUS_IS_OK(status)) { r->samr_handle.out.error_string = talloc_asprintf(mem_ctx, "SetUserInfo2 level 25 for [%s] failed: %s", r->samr_handle.in.account_name, nt_errstr(status)); } return status; }
/** Interface to the (hopefully) good crypto random number generator. Will always use /dev/urandom if available. **/ _PUBLIC_ void generate_secret_buffer(uint8_t *out, int len) { if (urand_fd == -1) { urand_fd = open( "/dev/urandom", O_RDONLY,0); if (urand_fd != -1) { smb_set_close_on_exec(urand_fd); } } if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { return; } generate_random_buffer(out, len); }
static PyObject *py_generate_random_bytes(PyObject *self, PyObject *args) { int len; PyObject *ret; uint8_t *bytes = NULL; if (!PyArg_ParseTuple(args, "i", &len)) return NULL; bytes = talloc_zero_size(NULL, len); generate_random_buffer(bytes, len); ret = PyBytes_FromStringAndSize((const char *)bytes, len); talloc_free(bytes); return ret; }
/* generate a random sid - used to build our own sid if we don't have one */ static void generate_random_sid(DOM_SID *sid) { int i; uchar raw_sid_data[12]; memset((char *)sid, '\0', sizeof(*sid)); sid->sid_rev_num = 1; sid->id_auth[5] = 5; sid->num_auths = 0; sid->sub_auths[sid->num_auths++] = 21; generate_random_buffer(raw_sid_data, 12, True); for (i = 0; i < 3; i++) sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4); }
void reset_globals_after_fork(void) { global_client_name_done = False; global_client_addr_done = False; /* * Re-seed the random crypto generator, so all smbd's * started from the same parent won't generate the same * sequence. */ { unsigned char dummy; generate_random_buffer( &dummy, 1, True); } }
static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx, const char *password, DATA_BLOB *auth_blob) { struct trustDomainPasswords auth_struct; struct AuthenticationInformation *auth_info_array; enum ndr_err_code ndr_err; size_t converted_size; generate_random_buffer(auth_struct.confounder, sizeof(auth_struct.confounder)); auth_info_array = talloc_array(mem_ctx, struct AuthenticationInformation, 1); if (auth_info_array == NULL) { return false; } auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR; if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password, strlen(password), &auth_info_array[0].AuthInfo.clear.password, &converted_size)) { return false; } auth_info_array[0].AuthInfo.clear.size = converted_size; auth_struct.outgoing.count = 1; auth_struct.outgoing.current.count = 1; auth_struct.outgoing.current.array = auth_info_array; auth_struct.outgoing.previous.count = 0; auth_struct.outgoing.previous.array = NULL; auth_struct.incoming.count = 1; auth_struct.incoming.current.count = 1; auth_struct.incoming.current.array = auth_info_array; auth_struct.incoming.previous.count = 0; auth_struct.incoming.previous.array = NULL; ndr_err = ndr_push_struct_blob(auth_blob, mem_ctx, &auth_struct, (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; } return true; }
/* generate a random sid - used to build our own sid if we don't have one */ static void generate_random_sid(struct dom_sid *sid) { int i; uchar raw_sid_data[12]; ZERO_STRUCTP(sid); sid->sid_rev_num = 1; sid->id_auth[5] = 5; sid->num_auths = 0; sid->sub_auths[sid->num_auths++] = 21; generate_random_buffer(raw_sid_data, 12); for (i = 0; i < 3; i++) sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4); }
int mit_samba_generate_salt(krb5_data *salt) { if (salt == NULL) { return EINVAL; } salt->length = 16; salt->data = malloc(salt->length); if (salt->data == NULL) { return ENOMEM; } generate_random_buffer((uint8_t *)salt->data, salt->length); return 0; }
char *generate_random_str(size_t len) { static unsigned char retstr[256]; size_t i; memset(retstr, '\0', sizeof(retstr)); if (len > sizeof(retstr)-1) len = sizeof(retstr) -1; generate_random_buffer( retstr, len); for (i = 0; i < len; i++) retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ]; retstr[i] = '\0'; return (char *)retstr; }
/* open up the secrets database with specified private_dir path */ bool secrets_init_path(const char *private_dir, bool use_ntdb) { char *fname = NULL; unsigned char dummy; TALLOC_CTX *frame; if (db_ctx != NULL) { return True; } if (private_dir == NULL) { return False; } frame = talloc_stackframe(); fname = talloc_asprintf(frame, "%s/secrets.%s", private_dir, use_ntdb ? "ntdb" : "tdb"); if (fname == NULL) { TALLOC_FREE(frame); return False; } db_ctx = db_open(NULL, fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db_ctx == NULL) { DEBUG(0,("Failed to open %s\n", fname)); TALLOC_FREE(frame); return False; } /** * Set a reseed function for the crypto random generator * * This avoids a problem where systems without /dev/urandom * could send the same challenge to multiple clients */ set_rand_reseed_callback(get_rand_seed, NULL); /* Ensure that the reseed is done now, while we are root, etc */ generate_random_buffer(&dummy, sizeof(dummy)); TALLOC_FREE(frame); return True; }
/*********************************************************** encode a password buffer with an already unicode password. The rest of the buffer is filled with random data to make it harder to attack. ************************************************************/ bool set_pw_in_buffer(uint8_t buffer[516], DATA_BLOB *password) { if (password->length > 512) { return false; } memcpy(&buffer[512 - password->length], password->data, password->length); generate_random_buffer(buffer, 512 - password->length); /* * The length of the new password is in the last 4 bytes of * the data buffer. */ SIVAL(buffer, 512, password->length); return true; }
/* seal a packet */ NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state); uint8_t digest_final[16]; uint8_t confounder[8]; uint8_t seq_num[8]; uint8_t sealing_key[16]; static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE; generate_random_buffer(confounder, 8); RSIVAL(seq_num, 0, state->seq_num); SIVAL(seq_num, 4, state->initiator?0x80:0); schannel_digest(state->creds->session_key, netsec_sig, confounder, data, length, digest_final); netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key); arcfour_crypt(confounder, sealing_key, 8); arcfour_crypt(data, sealing_key, length); netsec_deal_with_seq_num(state, digest_final, seq_num); (*sig) = data_blob_talloc(mem_ctx, NULL, 32); memcpy(sig->data, netsec_sig, 8); memcpy(sig->data+8, seq_num, 8); memcpy(sig->data+16, digest_final, 8); memcpy(sig->data+24, confounder, 8); dump_data_pw("signature:", sig->data+ 0, 8); dump_data_pw("seq_num :", sig->data+ 8, 8); dump_data_pw("digest :", sig->data+16, 8); dump_data_pw("confound :", sig->data+24, 8); return NT_STATUS_OK; }
static struct share_mode_data *fresh_share_mode_lock( TALLOC_CTX *mem_ctx, const char *servicepath, const struct smb_filename *smb_fname, const struct timespec *old_write_time) { struct share_mode_data *d; if ((servicepath == NULL) || (smb_fname == NULL) || (old_write_time == NULL)) { return NULL; } d = talloc_zero(mem_ctx, struct share_mode_data); if (d == NULL) { goto fail; } /* New record - new sequence number. */ generate_random_buffer((uint8_t *)&d->sequence_number, 8); d->base_name = talloc_strdup(d, smb_fname->base_name); if (d->base_name == NULL) { goto fail; } if (smb_fname->stream_name != NULL) { d->stream_name = talloc_strdup(d, smb_fname->stream_name); if (d->stream_name == NULL) { goto fail; } } d->servicepath = talloc_strdup(d, servicepath); if (d->servicepath == NULL) { goto fail; } d->old_write_time = *old_write_time; d->modified = false; d->fresh = true; return d; fail: DEBUG(0, ("talloc failed\n")); TALLOC_FREE(d); return NULL; }
/**************************************************************************** Try to get a challenge out of the various authentication modules. Returns a const char of length 8 bytes. ****************************************************************************/ _PUBLIC_ NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, uint8_t chal[8]) { NTSTATUS nt_status; struct auth_method_context *method; if (auth_ctx->challenge.data.length == 8) { DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n", auth_ctx->challenge.set_by)); memcpy(chal, auth_ctx->challenge.data.data, 8); return NT_STATUS_OK; } for (method = auth_ctx->methods; method; method = method->next) { nt_status = method->ops->get_challenge(method, auth_ctx, chal); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) { continue; } NT_STATUS_NOT_OK_RETURN(nt_status); auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8); NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data); auth_ctx->challenge.set_by = method->ops->name; break; } if (!auth_ctx->challenge.set_by) { generate_random_buffer(chal, 8); auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8); NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data); auth_ctx->challenge.set_by = "random"; auth_ctx->challenge.may_be_modified = true; } DEBUG(10,("auth_get_challenge: challenge set by %s\n", auth_ctx->challenge.set_by)); return NT_STATUS_OK; }
/*********************************************************** encode a password buffer with a unicode password. The buffer is filled with random data to make it harder to attack. ************************************************************/ BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags) { uchar new_pw[512]; size_t new_pw_len; new_pw_len = push_string(NULL, new_pw, password, sizeof(new_pw), string_flags); memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len); generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len); /* * The length of the new password is in the last 4 bytes of * the data buffer. */ SIVAL(buffer, 512, new_pw_len); ZERO_STRUCT(new_pw); return True; }
static DATA_BLOB NTLMv2_generate_client_data(const DATA_BLOB *names_blob) { uchar client_chal[8]; DATA_BLOB response = data_blob(NULL, 0); char long_date[8]; generate_random_buffer(client_chal, sizeof(client_chal)); put_long_date(long_date, time(NULL)); /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */ msrpc_gen(&response, "ddbbdb", 0x00000101, /* Header */ 0, /* 'Reserved' */ long_date, 8, /* Timestamp */ client_chal, 8, /* client challenge */ 0, /* Unknown */ names_blob->data, names_blob->length); /* End of name list */ return response; }
NTSTATUS auth_get_ntlm_challenge(struct auth_context *auth_context, uint8_t chal[8]) { uchar tmp[8]; if (auth_context->challenge.length) { DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge by module %s (normal)\n", auth_context->challenge_set_by)); memcpy(chal, auth_context->challenge.data, 8); return NT_STATUS_OK; } generate_random_buffer(tmp, sizeof(tmp)); auth_context->challenge = data_blob_talloc(auth_context, tmp, sizeof(tmp)); auth_context->challenge_set_by = "random"; memcpy(chal, auth_context->challenge.data, 8); return NT_STATUS_OK; }
void reset_globals_after_fork(void) { unsigned char dummy; /* * Increment the global seed value to ensure every smbd starts * with a new random seed. */ if (tdb) { int32 initial_val = sys_getpid(); tdb_change_int32_atomic(tdb, "INFO/random_seed", (int *)&initial_val, 1); set_rand_reseed_data((unsigned char *)&initial_val, sizeof(initial_val)); } /* * Re-seed the random crypto generator, so all smbd's * started from the same parent won't generate the same * sequence. */ generate_random_buffer( &dummy, 1, True); }