/* encode a buffer of bytes into a escaped string */ static char *encode_bytes(const char *ptr, unsigned len) { const char *hexdig = "0123456789abcdef"; char *ret, *p; unsigned i; ret = malloc(len*3 + 1); /* worst case size */ if (!ret) return NULL; for (p=ret,i=0;i<len;i++) { if (isalnum(ptr[i]) || isspace(ptr[i]) || (ispunct(ptr[i]) && !strchr("\\{}", ptr[i]))) { *p++ = ptr[i]; } else { unsigned char c = *(unsigned char *)(ptr+i); if (c == 0 && all_zero(ptr+i, len-i)) break; p[0] = '\\'; p[1] = hexdig[c>>4]; p[2] = hexdig[c&0xF]; p += 3; } } *p = 0; return ret; }
static void check_lun_is_wiped(unsigned char *buf, uint64_t lba) { unsigned char *rbuf = alloca(256 * block_size); READ16(sd, NULL, lba, 256 * block_size, block_size, 0, 0, 0, 0, 0, rbuf, EXPECT_STATUS_GOOD); if (rc16 == NULL) { return; } if (rc16->lbprz) { logging(LOG_VERBOSE, "LBPRZ==1 All blocks " "should read back as 0"); if (all_zero(rbuf, 256 * block_size) == 0) { logging(LOG_NORMAL, "[FAILED] Blocks did not " "read back as zero"); CU_FAIL("[FAILED] Blocks did not read back " "as zero"); } else { logging(LOG_VERBOSE, "[SUCCESS] Blocks read " "back as zero"); } } else { logging(LOG_VERBOSE, "LBPRZ==0 Blocks should not read back as " "all 'a' any more"); if (!memcmp(buf, rbuf, 256 * block_size)) { logging(LOG_NORMAL, "[FAILED] Blocks were not wiped"); CU_FAIL("[FAILED] Blocks were not wiped"); } else { logging(LOG_VERBOSE, "[SUCCESS] Blocks were wiped"); } } }
_PUBLIC_ BOOL GUID_all_zero(const struct GUID *u) { if (u->time_low != 0 || u->time_mid != 0 || u->time_hi_and_version != 0 || u->clock_seq[0] != 0 || u->clock_seq[1] != 0 || !all_zero(u->node, 6)) { return False; } return True; }
/* write all of mem_buffer to current sector */ bool AP_FlashStorage::write_all(void) { debug("write_all to sector %u at %u with reserved_space=%u\n", current_sector, write_offset, reserved_space); for (uint16_t ofs=0; ofs<storage_size; ofs += max_write) { if (!all_zero(ofs, max_write)) { if (!write(ofs, max_write)) { return false; } } } return true; }
void hexdump( char *desc, void *addr, int len ) { #define BYTE_LEN (16) // each byte is two characters (00-FF), plus the whitespace inbetween (BYTE_LEN // - 1 spaces) #define BYTE_LEN_HEXED (BYTE_LEN*2 + BYTE_LEN - 1) int i, isZero, beenZero, byte_len, hex_len; unsigned char bytes[BYTE_LEN+1], hexed[BYTE_LEN_HEXED+1]; unsigned char *pc = (unsigned char*)addr; if (desc != NULL) { printf("%s:\n", desc); } beenZero = 0; for (i = 0; i < len; i += byte_len) { hex_len = BYTE_LEN_HEXED; byte_len = MIN(BYTE_LEN, len - i); hexed[0] = '\0'; memcpy(bytes, &pc[i], byte_len); isZero = all_zero(bytes, byte_len); enhex(hexed, hex_len, bytes, byte_len); asciify(bytes, byte_len); if (!isZero) { beenZero = 0; } if (!beenZero) { hexed[hex_len] = '\0'; bytes[byte_len] = '\0'; printf("%04x %-*s %*s\n", i, hex_len, hexed, byte_len, bytes); if (isZero) { beenZero = 1; printf("*\n"); } } } printf("%04x\n", i); }
/* find the length of a nullterm array */ static int len_nullterm(const char *ptr, int size, int array_len) { int len; if (size == 1) { len = strnlen(ptr, array_len); } else { for (len=0;len<array_len;len++) { if (all_zero(ptr+len*size, size)) break; } } if (len == 0) len = 1; return len; }
int BladeSingleLogReader::ReadLog_() { int ret = BLADE_SUCCESS; if (log_buffer_.get_remain_data_len() > 0) { if (all_zero(log_buffer_.get_data() + log_buffer_.get_position(), log_buffer_.get_limit() - log_buffer_.get_position())) { pread_pos_ -= log_buffer_.get_limit() - log_buffer_.get_position(); log_buffer_.get_limit() = log_buffer_.get_position(); } else { memmove(log_buffer_.get_data(), log_buffer_.get_data() + log_buffer_.get_position(), log_buffer_.get_remain_data_len()); log_buffer_.get_limit() = log_buffer_.get_remain_data_len(); log_buffer_.get_position() = 0; } } else { log_buffer_.get_limit() = log_buffer_.get_position() = 0; } int64_t read_size = 0; ret = file_.pread(log_buffer_.get_data() + log_buffer_.get_limit(), log_buffer_.get_capacity() - log_buffer_.get_limit(), pread_pos_, read_size); // LOGV(LL_DEBUG, "pread:: pread_pos=%ld read_size=%ld buf_pos=%ld buf_limit=%ld", pread_pos_, read_size, log_buffer_.get_position(), log_buffer_.get_limit()); if (BLADE_SUCCESS != ret) { LOGV(LL_ERROR, "read log file[file_id=%lu] ret=%d", file_id_, ret); } else { // comment this log due to too frequent invoke by replay thread //LOGV(LL_DEBUG, "read %dB amount data from log file[file_id=%lu fd=%d]", err, file_id_, log_fd_); log_buffer_.get_limit() += read_size; pread_pos_ += read_size; if (0 == read_size) { // comment this log due to too frequent invoke by replay thread //LOGV(LL_DEBUG, "reach end of log file[file_id=%d]", file_id_); ret = BLADE_READ_NOTHING; } } return ret; }
static int one_accuracy_test(dofft_closure *k, aconstrain constrain, int sign, int n, C *a, C *b, double t[6]) { double err[6]; if (constrain) constrain(a, n); if (all_zero(a, n)) return 0; k->apply(k, a, b); fftaccuracy(n, a, b, sign, err); t[0] += err[0]; t[1] += err[1] * err[1]; t[2] = dmax(t[2], err[2]); t[3] += err[3]; t[4] += err[4] * err[4]; t[5] = dmax(t[5], err[5]); return 1; }
static void test_discovery_log(void) { struct spdk_nvmf_subsystem *subsystem; uint8_t buffer[8192]; struct spdk_nvmf_discovery_log_page *disc_log; struct spdk_nvmf_discovery_log_page_entry *entry; /* Reset discovery-related globals */ g_discovery_genctr = 0; free(g_discovery_log_page); g_discovery_log_page = NULL; g_discovery_log_page_size = 0; /* Add one subsystem and verify that the discovery log contains it */ subsystem = spdk_nvmf_create_subsystem("nqn.2016-06.io.spdk:subsystem1", SPDK_NVMF_SUBTYPE_NVME, NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL); SPDK_CU_ASSERT_FATAL(spdk_nvmf_subsystem_add_listener(subsystem, "test_transport1", "1234", "5678") == 0); /* Get only genctr (first field in the header) */ memset(buffer, 0xCC, sizeof(buffer)); disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; spdk_nvmf_get_discovery_log_page(buffer, 0, sizeof(disc_log->genctr)); CU_ASSERT(disc_log->genctr == 2); /* one added subsystem + one added listen address */ /* Get only the header, no entries */ memset(buffer, 0xCC, sizeof(buffer)); disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; spdk_nvmf_get_discovery_log_page(buffer, 0, sizeof(*disc_log)); CU_ASSERT(disc_log->genctr == 2); CU_ASSERT(disc_log->numrec == 1); /* Offset 0, exact size match */ memset(buffer, 0xCC, sizeof(buffer)); disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; spdk_nvmf_get_discovery_log_page(buffer, 0, sizeof(*disc_log) + sizeof(disc_log->entries[0])); CU_ASSERT(disc_log->genctr != 0); CU_ASSERT(disc_log->numrec == 1); CU_ASSERT(disc_log->entries[0].trtype == 42); /* Offset 0, oversize buffer */ memset(buffer, 0xCC, sizeof(buffer)); disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; spdk_nvmf_get_discovery_log_page(buffer, 0, sizeof(buffer)); CU_ASSERT(disc_log->genctr != 0); CU_ASSERT(disc_log->numrec == 1); CU_ASSERT(disc_log->entries[0].trtype == 42); CU_ASSERT(all_zero(buffer + sizeof(*disc_log) + sizeof(disc_log->entries[0]), sizeof(buffer) - (sizeof(*disc_log) + sizeof(disc_log->entries[0])))); /* Get just the first entry, no header */ memset(buffer, 0xCC, sizeof(buffer)); entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer; spdk_nvmf_get_discovery_log_page(buffer, offsetof(struct spdk_nvmf_discovery_log_page, entries[0]), sizeof(*entry)); CU_ASSERT(entry->trtype == 42); }
/* handle dumping of an array of arbitrary type */ static int gen_dump_array(struct parse_string *p, const struct parse_struct *pinfo, const char *ptr, int array_len, int indent) { int i, count=0; /* special handling of fixed length strings */ if (array_len != 0 && pinfo->ptr_count == 0 && pinfo->dump_fn == gen_dump_char) { char *s = encode_bytes(ptr, array_len); if (!s) return -1; if (addtabbed(p, pinfo->name, indent) || addstr(p, " = {") || addstr(p, s) || addstr(p, "}\n")) { free(s); return -1; } free(s); return 0; } for (i=0;i<array_len;i++) { const char *p2 = ptr; unsigned size = pinfo->size; /* generic pointer dereference */ if (pinfo->ptr_count) { p2 = *(const char **)ptr; size = sizeof(void *); } if ((count || pinfo->ptr_count) && !(pinfo->flags & FLAG_ALWAYS) && all_zero(ptr, size)) { ptr += size; continue; } if (count == 0) { if (addtabbed(p, pinfo->name, indent) || addshort(p, " = %u:", i)) { return -1; } } else { if (addshort(p, ", %u:", i) != 0) { return -1; } } if (gen_dump_one(p, pinfo, p2, indent) != 0) { return -1; } ptr += size; count++; } if (count) { return addstr(p, "\n"); } return 0; }
/** * Check whether the given password is one of the last two * password history entries. If so, the bad pwcount should * not be incremented even thought the actual password check * failed. */ static bool need_to_increment_bad_pw_count( const DATA_BLOB *challenge, struct samu* sampass, const struct auth_usersupplied_info *user_info) { uint8_t i; const uint8_t *pwhistory; uint32_t pwhistory_len; uint32_t policy_pwhistory_len; uint32_t acct_ctrl; const char *username; TALLOC_CTX *mem_ctx = talloc_stackframe(); bool result = true; pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &policy_pwhistory_len); if (policy_pwhistory_len == 0) { goto done; } pwhistory = pdb_get_pw_history(sampass, &pwhistory_len); if (!pwhistory || pwhistory_len == 0) { goto done; } acct_ctrl = pdb_get_acct_ctrl(sampass); username = pdb_get_username(sampass); for (i=1; i < MIN(MIN(3, policy_pwhistory_len), pwhistory_len); i++) { const uint8_t *salt; const uint8_t *nt_pw; NTSTATUS status; DATA_BLOB user_sess_key = data_blob_null; DATA_BLOB lm_sess_key = data_blob_null; salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN]; nt_pw = salt + PW_HISTORY_SALT_LEN; if (all_zero(nt_pw, NT_HASH_LEN)) { /* skip zero password hash */ continue; } if (!all_zero(salt, PW_HISTORY_SALT_LEN)) { /* skip nonzero salt (old format entry) */ continue; } status = sam_password_ok(mem_ctx, username, acct_ctrl, challenge, NULL, nt_pw, user_info, &user_sess_key, &lm_sess_key); if (NT_STATUS_IS_OK(status)) { result = false; break; } } done: TALLOC_FREE(mem_ctx); return result; }
static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx, struct netr_DELTA_USER *r, GROUPMAP *groupmap, ACCOUNTMAP *accountmap, FILE *add_fd, const char *sid, const char *suffix, int alloced) { fstring username, logonscript, homedrive, homepath = "", homedir = ""; fstring hex_nt_passwd, hex_lm_passwd; fstring description, profilepath, fullname, sambaSID; char *flags, *user_rdn; const char *ou; const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; uint32_t rid = 0, group_rid = 0, gidNumber = 0; time_t unix_time; int i, ret; /* Get the username */ fstrcpy(username, r->account_name.string); /* Get the rid */ rid = r->rid; /* Map the rid and username for group member info later */ accountmap->rid = rid; accountmap->cn = talloc_strdup(mem_ctx, username); NT_STATUS_HAVE_NO_MEMORY(accountmap->cn); /* Get the home directory */ if (r->acct_flags & ACB_NORMAL) { fstrcpy(homedir, r->home_directory.string); if (!*homedir) { snprintf(homedir, sizeof(homedir), "/home/%s", username); } else { snprintf(homedir, sizeof(homedir), "/nobodyshomedir"); } ou = lp_ldap_user_suffix(talloc_tos()); } else { ou = lp_ldap_machine_suffix(talloc_tos()); snprintf(homedir, sizeof(homedir), "/machinehomedir"); } /* Get the logon script */ fstrcpy(logonscript, r->logon_script.string); /* Get the home drive */ fstrcpy(homedrive, r->home_drive.string); /* Get the home path */ fstrcpy(homepath, r->home_directory.string); /* Get the description */ fstrcpy(description, r->description.string); /* Get the display name */ fstrcpy(fullname, r->full_name.string); /* Get the profile path */ fstrcpy(profilepath, r->profile_path.string); /* Get lm and nt password data */ if (!all_zero(r->lmpassword.hash, 16)) { pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags); } else { pdb_sethexpwd(hex_lm_passwd, NULL, 0); } if (!all_zero(r->ntpassword.hash, 16)) { pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags); } else { pdb_sethexpwd(hex_nt_passwd, NULL, 0); } unix_time = nt_time_to_unix(r->last_password_change); /* Increment the uid for the new user */ ldif_uid++; /* Set up group id and sambaSID for the user */ group_rid = r->primary_gid; for (i=0; i<alloced; i++) { if (groupmap[i].rid == group_rid) break; } if (i == alloced){ DEBUG(1, ("Could not find rid %d in groupmap array\n", group_rid)); return NT_STATUS_UNSUCCESSFUL; } gidNumber = groupmap[i].gidNumber; ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID); if (ret < 0 || ret == sizeof(sambaSID)) { return NT_STATUS_UNSUCCESSFUL; } /* Set up sambaAcctFlags */ flags = pdb_encode_acct_ctrl(r->acct_flags, NEW_PW_FORMAT_SPACE_PADDED_LEN); /* Add the user to the temporary add ldif file */ /* this isn't quite right...we can't assume there's just OU=. jmcd */ user_rdn = sstring_sub(ou, '=', ','); fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix); fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn, suffix); SAFE_FREE(user_rdn); fprintf(add_fd, "ObjectClass: top\n"); fprintf(add_fd, "objectClass: inetOrgPerson\n"); fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT); fprintf(add_fd, "objectClass: shadowAccount\n"); fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT); fprintf_attr(add_fd, "cn", "%s", username); fprintf_attr(add_fd, "sn", "%s", username); fprintf_attr(add_fd, "uid", "%s", username); fprintf(add_fd, "uidNumber: %d\n", ldif_uid); fprintf(add_fd, "gidNumber: %d\n", gidNumber); fprintf_attr(add_fd, "homeDirectory", "%s", homedir); if (*homepath) fprintf_attr(add_fd, "sambaHomePath", "%s", homepath); if (*homedrive) fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive); if (*logonscript) fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript); fprintf(add_fd, "loginShell: %s\n", ((r->acct_flags & ACB_NORMAL) ? "/bin/bash" : "/bin/false")); fprintf(add_fd, "gecos: System User\n"); if (*description) fprintf_attr(add_fd, "description", "%s", description); fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid); fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID); if(*fullname) fprintf_attr(add_fd, "displayName", "%s", fullname); if(*profilepath) fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath); if (strcmp(nopasswd, hex_lm_passwd) != 0) fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd); if (strcmp(nopasswd, hex_nt_passwd) != 0) fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd); fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time); fprintf(add_fd, "sambaAcctFlags: %s\n", flags); fprintf(add_fd, "\n"); fflush(add_fd); /* Return */ return NT_STATUS_OK; }
// process SCAN job static void process_scan_job(const hasher::job_t& job) { // print status print_status(job); size_t zero_count = 0; // get hash calculator object hasher::hash_calculator_t hash_calculator; // iterate over buffer to calculate and scan for block hashes for (size_t i=0; i < job.buffer_data_size; i+= job.step_size) { // skip if all the bytes are the same if (all_zero(job.buffer, job.buffer_size, i, job.block_size)) { ++zero_count; continue; } // calculate block hash const std::string block_hash = hash_calculator.calculate(job.buffer, job.buffer_size, i, job.block_size); // scan const std::string json_string = job.scan_manager->find_hash_json(job.scan_mode, block_hash); if (json_string.size() > 0) { // match so print offset <tab> file <tab> json std::stringstream ss; if (job.recursion_path != "") { // prepend recursion path before offset ss << job.recursion_path << "-"; } // add the offset ss << job.file_offset + i << "\t"; // add the block hash ss << hashdb::bin_to_hex(block_hash) << "\t"; // add the json text and a newline ss << json_string << "\n"; // print it hashdb::tprint(std::cout, ss.str()); } } // submit tracked zero_count to the scan tracker for final reporting job.scan_tracker->track_zero_count(zero_count); // submit tracked bytes processed to the scan tracker for final reporting if (job.recursion_depth == 0) { job.scan_tracker->track_bytes(job.buffer_data_size); } // recursively find and process any uncompressible data if (!job.disable_recursive_processing) { process_recursive(job); } // we are now done with this job. Delete it. delete[] job.buffer; delete &job; }
// process INGEST job static void process_ingest_job(const hasher::job_t& job) { // print status print_status(job); if (!job.disable_ingest_hashes) { // get hash calculator object hasher::hash_calculator_t hash_calculator; // get entropy calculator object hasher::entropy_calculator_t entropy_calculator(job.block_size); // iterate over buffer to add block hashes and metadata size_t zero_count = 0; size_t nonprobative_count = 0; for (size_t i=0; i < job.buffer_data_size; i+= job.step_size) { // skip if all the bytes are the same if (all_zero(job.buffer, job.buffer_size, i, job.block_size)) { ++zero_count; continue; } // calculate block hash const std::string block_hash = hash_calculator.calculate(job.buffer, job.buffer_size, i, job.block_size); // calculate entropy uint64_t k_entropy = 0; if (!job.disable_calculate_entropy) { k_entropy = entropy_calculator.calculate(job.buffer, job.buffer_size, i); } // calculate block label std::string block_label = ""; if (!job.disable_calculate_labels) { block_label = hasher::calculate_block_label(job.buffer, job.buffer_size, i, job.block_size); if (block_label.size() != 0) { ++nonprobative_count; } } // add block hash to DB job.import_manager->insert_hash(block_hash, k_entropy, block_label, job.file_hash, job.file_offset+i); } // submit tracked source counts to the ingest tracker for final reporting job.ingest_tracker->track_source( job.file_hash, zero_count, nonprobative_count); } // submit bytes processed to the ingest tracker for final reporting if (job.recursion_depth == 0) { job.ingest_tracker->track_bytes(job.buffer_data_size); } // recursively find and process any uncompressible data in order to // record their source names if (!job.disable_recursive_processing) { process_recursive(job); } // we are now done with this job. Delete it. delete[] job.buffer; delete &job; }
static int encode_audio(BitstreamWriter* bs, pcmreader* pcmreader, int signed_samples, unsigned block_size) { unsigned left_shift = 0; int sign_adjustment; /*allocate some temporary buffers*/ array_ia* frame = array_ia_new(); array_ia* wrapped_samples = array_ia_new(); array_i* shifted = array_i_new(); array_ia* deltas = array_ia_new(); array_i* residuals = array_i_new(); unsigned c; unsigned i; for (i = 0; i < pcmreader->channels; i++) wrapped_samples->append(wrapped_samples); if (!signed_samples) { sign_adjustment = 1 << (pcmreader->bits_per_sample - 1); } else { sign_adjustment = 0; } if (pcmreader->read(pcmreader, block_size, frame)) goto error; while (frame->_[0]->len > 0) { #ifndef STANDALONE Py_BEGIN_ALLOW_THREADS #endif if (frame->_[0]->len != block_size) { /*PCM frame count has changed, so issue BLOCKSIZE command*/ block_size = frame->_[0]->len; write_unsigned(bs, COMMAND_SIZE, FN_BLOCKSIZE); write_long(bs, block_size); } for (c = 0; c < frame->len; c++) { array_i* channel = frame->_[c]; array_i* wrapped = wrapped_samples->_[c]; /*convert signed samples to unsigned, if necessary*/ if (sign_adjustment != 0) for (i = 0; i < channel->len; i++) channel->_[i] += sign_adjustment; if (all_zero(channel)) { /*write ZERO command and wrap channel for next set*/ write_unsigned(bs, COMMAND_SIZE, FN_ZERO); wrapped->extend(wrapped, channel); wrapped->tail(wrapped, SAMPLES_TO_WRAP, wrapped); } else { unsigned diff = 1; unsigned energy = 0; unsigned wasted_BPS = wasted_bits(channel); if (wasted_BPS != left_shift) { /*issue BITSHIFT comand*/ left_shift = wasted_BPS; write_unsigned(bs, COMMAND_SIZE, FN_BITSHIFT); write_unsigned(bs, BITSHIFT_SIZE, left_shift); } /*apply left shift to channel data*/ if (left_shift > 0) { shifted->reset_for(shifted, channel->len); for (i = 0; i < channel->len; i++) a_append(shifted, channel->_[i] >> left_shift); } else { channel->copy(channel, shifted); } /*calculate best DIFF, energy and residuals for shifted data*/ calculate_best_diff(shifted, wrapped, deltas, &diff, &energy, residuals); /*issue DIFF command*/ write_unsigned(bs, COMMAND_SIZE, diff); write_unsigned(bs, ENERGY_SIZE, energy); for (i = 0; i < residuals->len; i++) write_signed(bs, energy, residuals->_[i]); /*wrap shifted channel data for next set*/ wrapped->extend(wrapped, shifted); wrapped->tail(wrapped, SAMPLES_TO_WRAP, wrapped); } }
static NTSTATUS authsam_password_check_and_record(struct auth4_context *auth_context, TALLOC_CTX *mem_ctx, struct ldb_dn *domain_dn, struct ldb_message *msg, uint16_t acct_flags, const struct auth_usersupplied_info *user_info, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key, bool *authoritative) { NTSTATUS nt_status; NTSTATUS auth_status; TALLOC_CTX *tmp_ctx; int i, ret; int history_len = 0; struct ldb_context *sam_ctx = auth_context->sam_ctx; const char * const attrs[] = { "pwdHistoryLength", NULL }; struct ldb_message *dom_msg; struct samr_Password *lm_pwd; struct samr_Password *nt_pwd; bool am_rodc; tmp_ctx = talloc_new(mem_ctx); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } /* * This call does more than what it appears to do, it also * checks for the account lockout. * * It is done here so that all parts of Samba that read the * password refuse to even operate on it if the account is * locked out, to avoid mistakes like CVE-2013-4496. */ nt_status = samdb_result_passwords(tmp_ctx, auth_context->lp_ctx, msg, &lm_pwd, &nt_pwd); if (!NT_STATUS_IS_OK(nt_status)) { TALLOC_FREE(tmp_ctx); return nt_status; } if (lm_pwd == NULL && nt_pwd == NULL) { if (samdb_rodc(auth_context->sam_ctx, &am_rodc) == LDB_SUCCESS && am_rodc) { /* * we don't have passwords for this * account. We are an RODC, and this account * may be one for which we either are denied * REPL_SECRET replication or we haven't yet * done the replication. We return * NT_STATUS_NOT_IMPLEMENTED which tells the * auth code to try the next authentication * mechanism. We also send a message to our * drepl server to tell it to try and * replicate the secrets for this account. * * TODO: Should we only trigger this is detected * there's a chance that the password might be * replicated, we should be able to detect this * based on msDS-NeverRevealGroup. */ auth_sam_trigger_repl_secret(auth_context, auth_context->msg_ctx, auth_context->event_ctx, msg->dn); TALLOC_FREE(tmp_ctx); return NT_STATUS_NOT_IMPLEMENTED; } } auth_status = authsam_password_ok(auth_context, tmp_ctx, acct_flags, lm_pwd, nt_pwd, user_info, user_sess_key, lm_sess_key); if (NT_STATUS_IS_OK(auth_status)) { if (user_sess_key->data) { talloc_steal(mem_ctx, user_sess_key->data); } if (lm_sess_key->data) { talloc_steal(mem_ctx, lm_sess_key->data); } TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; } *user_sess_key = data_blob_null; *lm_sess_key = data_blob_null; if (!NT_STATUS_EQUAL(auth_status, NT_STATUS_WRONG_PASSWORD)) { TALLOC_FREE(tmp_ctx); return auth_status; } /* * We only continue if this was a wrong password * and we'll always return NT_STATUS_WRONG_PASSWORD * no matter what error happens. */ /* pull the domain password property attributes */ ret = dsdb_search_one(sam_ctx, tmp_ctx, &dom_msg, domain_dn, LDB_SCOPE_BASE, attrs, 0, "objectClass=domain"); if (ret == LDB_SUCCESS) { history_len = ldb_msg_find_attr_as_uint(dom_msg, "pwdHistoryLength", 0); } else if (ret == LDB_ERR_NO_SUCH_OBJECT) { DEBUG(3,("Couldn't find domain %s: %s!\n", ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); } else { DEBUG(3,("error finding domain %s: %s!\n", ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); } for (i = 1; i < MIN(history_len, 3); i++) { struct samr_Password zero_string_hash; struct samr_Password zero_string_des_hash; struct samr_Password *nt_history_pwd = NULL; struct samr_Password *lm_history_pwd = NULL; NTTIME pwdLastSet; struct timeval tv_now; NTTIME now; int allowed_period_mins; NTTIME allowed_period; nt_status = samdb_result_passwords_from_history(tmp_ctx, auth_context->lp_ctx, msg, i, &lm_history_pwd, &nt_history_pwd); if (!NT_STATUS_IS_OK(nt_status)) { /* * If we don't find element 'i' we won't find * 'i+1' ... */ break; } /* * We choose to avoid any issues * around different LM and NT history * lengths by only checking the NT * history */ if (nt_history_pwd == NULL) { /* * If we don't find element 'i' we won't find * 'i+1' ... */ break; } /* Skip over all-zero hashes in the history */ if (all_zero(nt_history_pwd->hash, sizeof(nt_history_pwd->hash))) { continue; } /* * This looks odd, but the password_hash module writes this in if * (somehow) we didn't have an old NT hash */ E_md4hash("", zero_string_hash.hash); if (memcmp(nt_history_pwd->hash, zero_string_hash.hash, 16) == 0) { continue; } E_deshash("", zero_string_des_hash.hash); if (!lm_history_pwd || memcmp(lm_history_pwd->hash, zero_string_des_hash.hash, 16) == 0) { lm_history_pwd = NULL; } auth_status = authsam_password_ok(auth_context, tmp_ctx, acct_flags, lm_history_pwd, nt_history_pwd, user_info, user_sess_key, lm_sess_key); if (!NT_STATUS_IS_OK(auth_status)) { /* * If this was not a correct password, try the next * one from the history */ *user_sess_key = data_blob_null; *lm_sess_key = data_blob_null; continue; } if (i != 1) { /* * The authentication was OK, but not against * the previous password, which is stored at index 1. * * We just return the original wrong password. * This skips the update of the bad pwd count, * because this is almost certainly user error * (or automatic login on a computer using a cached * password from before the password change), * not an attack. */ TALLOC_FREE(tmp_ctx); return NT_STATUS_WRONG_PASSWORD; } if (user_info->password_state != AUTH_PASSWORD_RESPONSE) { /* * The authentication was OK against the previous password, * but it's not a NTLM network authentication. * * We just return the original wrong password. * This skips the update of the bad pwd count, * because this is almost certainly user error * (or automatic login on a computer using a cached * password from before the password change), * not an attack. */ TALLOC_FREE(tmp_ctx); return NT_STATUS_WRONG_PASSWORD; } /* * If the password was OK, it's a NTLM network authentication * and it was the previous password. * * Now we see if it is within the grace period, * so that we don't break cached sessions on other computers * before the user can lock and unlock their other screens * (resetting their cached password). * * See http://support.microsoft.com/kb/906305 * OldPasswordAllowedPeriod ("old password allowed period") * is specified in minutes. The default is 60. */ allowed_period_mins = lpcfg_old_password_allowed_period(auth_context->lp_ctx); /* * NTTIME uses 100ns units */ allowed_period = allowed_period_mins * 60 * 1000*1000*10; pwdLastSet = samdb_result_nttime(msg, "pwdLastSet", 0); tv_now = timeval_current(); now = timeval_to_nttime(&tv_now); if (now < pwdLastSet) { /* * time jump? * * We just return the original wrong password. * This skips the update of the bad pwd count, * because this is almost certainly user error * (or automatic login on a computer using a cached * password from before the password change), * not an attack. */ TALLOC_FREE(tmp_ctx); return NT_STATUS_WRONG_PASSWORD; } if ((now - pwdLastSet) >= allowed_period) { /* * The allowed period is over. * * We just return the original wrong password. * This skips the update of the bad pwd count, * because this is almost certainly user error * (or automatic login on a computer using a cached * password from before the password change), * not an attack. */ TALLOC_FREE(tmp_ctx); return NT_STATUS_WRONG_PASSWORD; } /* * We finally allow the authentication with the * previous password within the allowed period. */ if (user_sess_key->data) { talloc_steal(mem_ctx, user_sess_key->data); } if (lm_sess_key->data) { talloc_steal(mem_ctx, lm_sess_key->data); } TALLOC_FREE(tmp_ctx); return auth_status; } /* * If we are not in the allowed period or match an old password, * we didn't return early. Now update the badPwdCount et al. */ nt_status = authsam_update_bad_pwd_count(auth_context->sam_ctx, msg, domain_dn); if (!NT_STATUS_IS_OK(nt_status)) { /* * We need to return the original * NT_STATUS_WRONG_PASSWORD error, so there isn't * anything more we can do than write something into * the log */ DEBUG(0, ("Failed to note bad password for user [%s]: %s\n", user_info->mapped.account_name, nt_errstr(nt_status))); } if (samdb_rodc(auth_context->sam_ctx, &am_rodc) == LDB_SUCCESS && am_rodc) { *authoritative = false; } TALLOC_FREE(tmp_ctx); return NT_STATUS_WRONG_PASSWORD; }
/* the generic dump routine. Scans the parse information for this structure and processes it recursively */ char *gen_dump(const struct parse_struct *pinfo, const char *data, unsigned indent) { struct parse_string p; int i; p.length = 0; p.allocated = 0; p.s = NULL; if (addstr(&p, "") != 0) { return NULL; } for (i=0;pinfo[i].name;i++) { const char *ptr = data + pinfo[i].offset; unsigned size = pinfo[i].size; if (pinfo[i].ptr_count) { size = sizeof(void *); } /* special handling for array types */ if (pinfo[i].array_len) { unsigned len = pinfo[i].array_len; if (pinfo[i].flags & FLAG_NULLTERM) { len = len_nullterm(ptr, size, len); } if (gen_dump_array(&p, &pinfo[i], ptr, len, indent)) { goto failed; } continue; } /* and dynamically sized arrays */ if (pinfo[i].dynamic_len) { int len = find_var(pinfo, data, pinfo[i].dynamic_len); struct parse_struct p2 = pinfo[i]; if (len < 0) { goto failed; } if (len > 0) { if (pinfo[i].flags & FLAG_NULLTERM) { len = len_nullterm(*(char **)ptr, pinfo[i].size, len); } p2.ptr_count--; p2.dynamic_len = NULL; if (gen_dump_array(&p, &p2, *(char **)ptr, len, indent) != 0) { goto failed; } } continue; } /* don't dump zero elements */ if (!(pinfo[i].flags & FLAG_ALWAYS) && all_zero(ptr, size)) continue; /* assume char* is a null terminated string */ if (pinfo[i].size == 1 && pinfo[i].ptr_count == 1 && pinfo[i].dump_fn == gen_dump_char) { if (gen_dump_string(&p, &pinfo[i], ptr, indent) != 0) { goto failed; } continue; } /* generic pointer dereference */ if (pinfo[i].ptr_count) { ptr = *(const char **)ptr; } if (addtabbed(&p, pinfo[i].name, indent) || addstr(&p, " = ") || gen_dump_one(&p, &pinfo[i], ptr, indent) || addstr(&p, "\n")) { goto failed; } } return p.s; failed: free(p.s); return NULL; }