NTSTATUS evlog_convert_tdb_to_evt(TALLOC_CTX *mem_ctx, ELOG_TDB *etdb, DATA_BLOB *blob_p, uint32_t *num_records_p) { NTSTATUS status = NT_STATUS_OK; enum ndr_err_code ndr_err; DATA_BLOB blob; uint32_t num_records = 0; struct EVENTLOG_EVT_FILE evt; uint32_t count = 1; size_t endoffset = 0; ZERO_STRUCT(evt); while (1) { struct eventlog_Record_tdb *r; struct EVENTLOGRECORD e; r = evlog_pull_record_tdb(mem_ctx, etdb->tdb, count); if (!r) { break; } status = evlog_tdb_entry_to_evt_entry(mem_ctx, r, &e); if (!NT_STATUS_IS_OK(status)) { goto done; } endoffset += ndr_size_EVENTLOGRECORD(&e, NULL, 0); ADD_TO_ARRAY(mem_ctx, struct EVENTLOGRECORD, e, &evt.records, &num_records); count++; } evt.hdr.StartOffset = 0x30; evt.hdr.EndOffset = evt.hdr.StartOffset + endoffset; evt.hdr.CurrentRecordNumber = count; evt.hdr.OldestRecordNumber = 1; evt.hdr.MaxSize = tdb_fetch_int32(etdb->tdb, EVT_MAXSIZE); evt.hdr.Flags = 0; evt.hdr.Retention = tdb_fetch_int32(etdb->tdb, EVT_RETENTION); if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(EVENTLOGHEADER, &evt.hdr); } evt.eof.BeginRecord = 0x30; evt.eof.EndRecord = evt.hdr.StartOffset + endoffset; evt.eof.CurrentRecordNumber = evt.hdr.CurrentRecordNumber; evt.eof.OldestRecordNumber = evt.hdr.OldestRecordNumber; if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(EVENTLOGEOF, &evt.eof); } ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &evt, (ndr_push_flags_fn_t)ndr_push_EVENTLOG_EVT_FILE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); goto done; } *blob_p = blob; *num_records_p = num_records; done: return status; }
static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, const struct drsuapi_DsReplicaAttribute *in, TALLOC_CTX *mem_ctx, struct ldb_message_element *out) { uint32_t i; int ret; out->flags = 0; out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName); W_ERROR_HAVE_NO_MEMORY(out->name); out->num_values = in->value_ctr.num_values; out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values); W_ERROR_HAVE_NO_MEMORY(out->values); for (i=0; i < out->num_values; i++) { struct drsuapi_DsReplicaObjectIdentifier3 id3; enum ndr_err_code ndr_err; DATA_BLOB guid_blob; struct ldb_dn *dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { W_ERROR_HAVE_NO_MEMORY(tmp_ctx); } if (in->value_ctr.values[i].blob == NULL) { talloc_free(tmp_ctx); return WERR_FOOBAR; } if (in->value_ctr.values[i].blob->length == 0) { talloc_free(tmp_ctx); return WERR_FOOBAR; } ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob, tmp_ctx, schema->iconv_convenience, &id3, (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } dn = ldb_dn_new(tmp_ctx, ldb, id3.dn); if (!dn) { talloc_free(tmp_ctx); /* If this fails, it must be out of memory, as it does not do much parsing */ W_ERROR_HAVE_NO_MEMORY(dn); } ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid, (ndr_push_flags_fn_t)ndr_push_GUID); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return WERR_FOOBAR; } talloc_free(guid_blob.data); if (id3.__ndr_size_sid) { DATA_BLOB sid_blob; ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid, (ndr_push_flags_fn_t)ndr_push_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return WERR_FOOBAR; } } out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1)); talloc_free(tmp_ctx); } return WERR_OK; }
NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp, const DATA_BLOB old_cookie, TALLOC_CTX *mem_ctx, DATA_BLOB *new_cookie) { struct connection_struct *conn = fsp->conn; NTSTATUS status; enum ndr_err_code ndr_err; struct vfs_default_durable_cookie cookie; DATA_BLOB new_cookie_blob = data_blob_null; struct share_mode_lock *lck; bool ok; *new_cookie = data_blob_null; ZERO_STRUCT(cookie); ndr_err = ndr_pull_struct_blob(&old_cookie, talloc_tos(), &cookie, (ndr_pull_flags_fn_t)ndr_pull_vfs_default_durable_cookie); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); return status; } if (strcmp(cookie.magic, VFS_DEFAULT_DURABLE_COOKIE_MAGIC) != 0) { return NT_STATUS_INVALID_PARAMETER; } if (cookie.version != VFS_DEFAULT_DURABLE_COOKIE_VERSION) { return NT_STATUS_INVALID_PARAMETER; } if (!file_id_equal(&fsp->file_id, &cookie.id)) { return NT_STATUS_INVALID_PARAMETER; } if (!BATCH_OPLOCK_TYPE(fsp->oplock_type)) { return NT_STATUS_NOT_SUPPORTED; } /* * For now let it be simple and do not keep * delete on close files durable open */ if (fsp->initial_delete_on_close) { return NT_STATUS_NOT_SUPPORTED; } if (fsp->delete_on_close) { return NT_STATUS_NOT_SUPPORTED; } if (!VALID_STAT(fsp->fsp_name->st)) { return NT_STATUS_NOT_SUPPORTED; } if (!S_ISREG(fsp->fsp_name->st.st_ex_mode)) { return NT_STATUS_NOT_SUPPORTED; } /* Ensure any pending write time updates are done. */ if (fsp->update_write_time_event) { update_write_time_handler(fsp->conn->sconn->ev_ctx, fsp->update_write_time_event, timeval_current(), (void *)fsp); } /* * The above checks are done in mark_share_mode_disconnected() too * but we want to avoid getting the lock if possible */ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); if (lck != NULL) { struct smb_file_time ft; ZERO_STRUCT(ft); if (fsp->write_time_forced) { ft.mtime = lck->data->changed_write_time; } else if (fsp->update_write_time_on_close) { if (null_timespec(fsp->close_write_time)) { ft.mtime = timespec_current(); } else { ft.mtime = fsp->close_write_time; } } if (!null_timespec(ft.mtime)) { round_timespec(conn->ts_res, &ft.mtime); file_ntimes(conn, fsp->fsp_name, &ft); } ok = mark_share_mode_disconnected(lck, fsp); if (!ok) { TALLOC_FREE(lck); } } if (lck != NULL) { ok = brl_mark_disconnected(fsp); if (!ok) { TALLOC_FREE(lck); } } if (lck == NULL) { return NT_STATUS_NOT_SUPPORTED; } TALLOC_FREE(lck); status = vfs_stat_fsp(fsp); if (!NT_STATUS_IS_OK(status)) { return status; } ZERO_STRUCT(cookie); cookie.allow_reconnect = true; cookie.id = fsp->file_id; cookie.servicepath = conn->connectpath; cookie.base_name = fsp->fsp_name->base_name; cookie.initial_allocation_size = fsp->initial_allocation_size; cookie.position_information = fsp->fh->position_information; cookie.update_write_time_triggered = fsp->update_write_time_triggered; cookie.update_write_time_on_close = fsp->update_write_time_on_close; cookie.write_time_forced = fsp->write_time_forced; cookie.close_write_time = fsp->close_write_time; cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev; cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino; cookie.stat_info.st_ex_mode = fsp->fsp_name->st.st_ex_mode; cookie.stat_info.st_ex_nlink = fsp->fsp_name->st.st_ex_nlink; cookie.stat_info.st_ex_uid = fsp->fsp_name->st.st_ex_uid; cookie.stat_info.st_ex_gid = fsp->fsp_name->st.st_ex_gid; cookie.stat_info.st_ex_rdev = fsp->fsp_name->st.st_ex_rdev; cookie.stat_info.st_ex_size = fsp->fsp_name->st.st_ex_size; cookie.stat_info.st_ex_atime = fsp->fsp_name->st.st_ex_atime; cookie.stat_info.st_ex_mtime = fsp->fsp_name->st.st_ex_mtime; cookie.stat_info.st_ex_ctime = fsp->fsp_name->st.st_ex_ctime; cookie.stat_info.st_ex_btime = fsp->fsp_name->st.st_ex_btime; cookie.stat_info.st_ex_calculated_birthtime = fsp->fsp_name->st.st_ex_calculated_birthtime; cookie.stat_info.st_ex_blksize = fsp->fsp_name->st.st_ex_blksize; cookie.stat_info.st_ex_blocks = fsp->fsp_name->st.st_ex_blocks; cookie.stat_info.st_ex_flags = fsp->fsp_name->st.st_ex_flags; cookie.stat_info.st_ex_mask = fsp->fsp_name->st.st_ex_mask; ndr_err = ndr_push_struct_blob(&new_cookie_blob, mem_ctx, &cookie, (ndr_push_flags_fn_t)ndr_push_vfs_default_durable_cookie); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); return status; } status = fd_close(fsp); if (!NT_STATUS_IS_OK(status)) { data_blob_free(&new_cookie_blob); return status; } *new_cookie = new_cookie_blob; return NT_STATUS_OK; }
NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx, TDB_CONTEXT *tdb, struct eventlog_Record_tdb *r, uint32_t *record_number) { TDB_DATA kbuf, ebuf; DATA_BLOB blob; enum ndr_err_code ndr_err; int ret; if (!r) { return NT_STATUS_INVALID_PARAMETER; } if (!can_write_to_eventlog(tdb, r->size)) { return NT_STATUS_EVENTLOG_CANT_START; } /* need to read the record number and insert it into the entry here */ /* lock */ ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1); if (ret == -1) { return NT_STATUS_LOCK_NOT_GRANTED; } /* read */ r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD); ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r, (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); return ndr_map_error2ntstatus(ndr_err); } /* increment the record count */ kbuf.dsize = sizeof(int32_t); kbuf.dptr = (uint8_t *)&r->record_number; ebuf.dsize = blob.length; ebuf.dptr = blob.data; ret = tdb_store(tdb, kbuf, ebuf, 0); if (ret == -1) { tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); return NT_STATUS_EVENTLOG_FILE_CORRUPT; } ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1); if (ret == -1) { tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); return NT_STATUS_EVENTLOG_FILE_CORRUPT; } tdb_unlock_bystring(tdb, EVT_NEXT_RECORD); if (record_number) { *record_number = r->record_number; } return NT_STATUS_OK; }
WERROR dns_verify_tsig(struct dns_server *dns, TALLOC_CTX *mem_ctx, struct dns_request_state *state, struct dns_name_packet *packet, DATA_BLOB *in) { WERROR werror; NTSTATUS status; enum ndr_err_code ndr_err; bool found_tsig = false; uint16_t i, arcount = 0; DATA_BLOB tsig_blob, fake_tsig_blob, sig; uint8_t *buffer = NULL; size_t buffer_len = 0, packet_len = 0; struct dns_server_tkey *tkey = NULL; struct dns_fake_tsig_rec *check_rec = talloc_zero(mem_ctx, struct dns_fake_tsig_rec); /* Find the first TSIG record in the additional records */ for (i=0; i < packet->arcount; i++) { if (packet->additional[i].rr_type == DNS_QTYPE_TSIG) { found_tsig = true; break; } } if (!found_tsig) { return WERR_OK; } /* The TSIG record needs to be the last additional record */ if (found_tsig && i + 1 != packet->arcount) { DEBUG(1, ("TSIG record not the last additional record!\n")); return DNS_ERR(FORMAT_ERROR); } /* We got a TSIG, so we need to sign our reply */ state->sign = true; state->tsig = talloc_zero(state->mem_ctx, struct dns_res_rec); if (state->tsig == NULL) { return WERR_NOT_ENOUGH_MEMORY; } werror = dns_copy_tsig(state->tsig, &packet->additional[i], state->tsig); if (!W_ERROR_IS_OK(werror)) { return werror; } packet->arcount--; tkey = dns_find_tkey(dns->tkeys, state->tsig->name); if (tkey == NULL) { /* * We must save the name for use in the TSIG error * response and have no choice here but to save the * keyname from the TSIG request. */ state->key_name = talloc_strdup(state->mem_ctx, state->tsig->name); if (state->key_name == NULL) { return WERR_NOT_ENOUGH_MEMORY; } state->tsig_error = DNS_RCODE_BADKEY; return DNS_ERR(NOTAUTH); } /* * Remember the keyname that found an existing tkey, used * later to fetch the key with dns_find_tkey() when signing * and adding a TSIG record with MAC. */ state->key_name = talloc_strdup(state->mem_ctx, tkey->name); if (state->key_name == NULL) { return WERR_NOT_ENOUGH_MEMORY; } /* FIXME: check TSIG here */ if (check_rec == NULL) { return WERR_NOT_ENOUGH_MEMORY; } /* first build and verify check packet */ check_rec->name = talloc_strdup(check_rec, tkey->name); if (check_rec->name == NULL) { return WERR_NOT_ENOUGH_MEMORY; } check_rec->rr_class = DNS_QCLASS_ANY; check_rec->ttl = 0; check_rec->algorithm_name = talloc_strdup(check_rec, tkey->algorithm); if (check_rec->algorithm_name == NULL) { return WERR_NOT_ENOUGH_MEMORY; } check_rec->time_prefix = 0; check_rec->time = state->tsig->rdata.tsig_record.time; check_rec->fudge = state->tsig->rdata.tsig_record.fudge; check_rec->error = 0; check_rec->other_size = 0; check_rec->other_data = NULL; ndr_err = ndr_push_struct_blob(&tsig_blob, mem_ctx, state->tsig, (ndr_push_flags_fn_t)ndr_push_dns_res_rec); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("Failed to push packet: %s!\n", ndr_errstr(ndr_err))); return DNS_ERR(SERVER_FAILURE); } ndr_err = ndr_push_struct_blob(&fake_tsig_blob, mem_ctx, check_rec, (ndr_push_flags_fn_t)ndr_push_dns_fake_tsig_rec); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("Failed to push packet: %s!\n", ndr_errstr(ndr_err))); return DNS_ERR(SERVER_FAILURE); } /* we need to work some magic here. we need to keep the input packet * exactly like we got it, but we need to cut off the tsig record */ packet_len = in->length - tsig_blob.length; buffer_len = packet_len + fake_tsig_blob.length; buffer = talloc_zero_array(mem_ctx, uint8_t, buffer_len); if (buffer == NULL) { return WERR_NOT_ENOUGH_MEMORY; } memcpy(buffer, in->data, packet_len); memcpy(buffer + packet_len, fake_tsig_blob.data, fake_tsig_blob.length); sig.length = state->tsig->rdata.tsig_record.mac_size; sig.data = talloc_memdup(mem_ctx, state->tsig->rdata.tsig_record.mac, sig.length); if (sig.data == NULL) { return WERR_NOT_ENOUGH_MEMORY; } /* Now we also need to count down the additional record counter */ arcount = RSVAL(buffer, 10); RSSVAL(buffer, 10, arcount-1); status = gensec_check_packet(tkey->gensec, buffer, buffer_len, buffer, buffer_len, &sig); if (NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) { state->tsig_error = DNS_RCODE_BADSIG; return DNS_ERR(NOTAUTH); } if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Verifying tsig failed: %s\n", nt_errstr(status))); return ntstatus_to_werror(status); } state->authenticated = true; return WERR_OK; }
if (b9_record_match(state, rec, &rec2)) { break; } } if (i == el->num_values) { /* adding a new value */ el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values+1); if (el->values == NULL) { talloc_free(rec); return ISC_R_NOMEMORY; } el->num_values++; } ndr_err = ndr_push_struct_blob(&el->values[i], rec, rec, (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { state->log(ISC_LOG_ERROR, "samba_dlz: failed to push dnsRecord for %s", ldb_dn_get_linearized(dn)); talloc_free(rec); return ISC_R_FAILURE; } if (!b9_set_session_info(state, name)) { talloc_free(rec); return ISC_R_FAILURE; } /* modify the record */ el->flags = LDB_FLAG_MOD_REPLACE;
static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *values ) { struct spoolss_DeviceMode *devmode; UNISTR2 data; char *p; uint32 printer_status = PRINTER_STATUS_OK; regval_ctr_addvalue( values, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) ); regval_ctr_addvalue( values, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) ); regval_ctr_addvalue( values, "ChangeID", REG_DWORD, (char*)&info2->changeid, sizeof(info2->changeid) ); regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) ); /* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */ regval_ctr_addvalue( values, "Status", REG_DWORD, (char*)&printer_status, sizeof(info2->status) ); regval_ctr_addvalue( values, "StartTime", REG_DWORD, (char*)&info2->starttime, sizeof(info2->starttime) ); regval_ctr_addvalue( values, "UntilTime", REG_DWORD, (char*)&info2->untiltime, sizeof(info2->untiltime) ); /* strip the \\server\ from this string */ if ( !(p = strrchr( info2->printername, '\\' ) ) ) p = info2->printername; else p++; init_unistr2( &data, p, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, info2->location, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, info2->comment, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, info2->portname, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Print Processor", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); init_unistr2( &data, "RAW", UNI_STR_TERMINATE); regval_ctr_addvalue( values, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); /* stream the device mode */ devmode = construct_dev_mode(values,info2->sharename); if (devmode) { DATA_BLOB blob; enum ndr_err_code ndr_err; ndr_err = ndr_push_struct_blob(&blob, values, NULL, devmode, (ndr_push_flags_fn_t)ndr_push_spoolss_DeviceMode); if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { regval_ctr_addvalue(values, "Default Devmode", REG_BINARY, (const char *)blob.data, blob.length); } } /* stream the printer security descriptor */ if (info2->secdesc_buf && info2->secdesc_buf->sd && info2->secdesc_buf->sd_size) { NTSTATUS status; DATA_BLOB blob; status = marshall_sec_desc(values, info2->secdesc_buf->sd, &blob.data, &blob.length); if (NT_STATUS_IS_OK(status)) { regval_ctr_addvalue(values, "Security", REG_BINARY, (const char *)blob.data, blob.length); } } return; }
static NTSTATUS smbXsrv_open_global_store(struct smbXsrv_open_global0 *global) { struct smbXsrv_open_globalB global_blob; DATA_BLOB blob = data_blob_null; TDB_DATA key; TDB_DATA val; NTSTATUS status; enum ndr_err_code ndr_err; /* * TODO: if we use other versions than '0' * we would add glue code here, that would be able to * store the information in the old format. */ if (global->db_rec == NULL) { return NT_STATUS_INTERNAL_ERROR; } key = dbwrap_record_get_key(global->db_rec); val = dbwrap_record_get_value(global->db_rec); ZERO_STRUCT(global_blob); global_blob.version = smbXsrv_version_global_current(); if (val.dsize >= 8) { global_blob.seqnum = IVAL(val.dptr, 4); } global_blob.seqnum += 1; global_blob.info.info0 = global; ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob, (ndr_push_flags_fn_t)ndr_push_smbXsrv_open_globalB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(1,("smbXsrv_open_global_store: key '%s' ndr_push - %s\n", hex_encode_talloc(global->db_rec, key.dptr, key.dsize), nt_errstr(status))); TALLOC_FREE(global->db_rec); return status; } val = make_tdb_data(blob.data, blob.length); status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("smbXsrv_open_global_store: key '%s' store - %s\n", hex_encode_talloc(global->db_rec, key.dptr, key.dsize), nt_errstr(status))); TALLOC_FREE(global->db_rec); return status; } if (CHECK_DEBUGLVL(10)) { DEBUG(10,("smbXsrv_open_global_store: key '%s' stored\n", hex_encode_talloc(global->db_rec, key.dptr, key.dsize))); NDR_PRINT_DEBUG(smbXsrv_open_globalB, &global_blob); } TALLOC_FREE(global->db_rec); return NT_STATUS_OK; }
bool send_getdc_request(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx, struct sockaddr_storage *dc_ss, const char *domain_name, const DOM_SID *sid, uint32_t nt_version) { struct in_addr dc_ip; const char *my_acct_name = NULL; const char *my_mailslot = NULL; struct nbt_netlogon_packet packet; struct NETLOGON_SAM_LOGON_REQUEST *s; enum ndr_err_code ndr_err; DATA_BLOB blob; struct dom_sid my_sid; ZERO_STRUCT(packet); ZERO_STRUCT(my_sid); if (dc_ss->ss_family != AF_INET) { return false; } if (sid) { my_sid = *sid; } dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; my_mailslot = mailslot_name(mem_ctx, dc_ip); if (!my_mailslot) { return false; } my_acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); if (!my_acct_name) { return false; } packet.command = LOGON_SAM_LOGON_REQUEST; s = &packet.req.logon; s->request_count = 0; s->computer_name = global_myname(); s->user_name = my_acct_name; s->mailslot_name = my_mailslot; s->acct_control = ACB_WSTRUST; s->sid = my_sid; s->nt_version = nt_version; s->lmnt_token = 0xffff; s->lm20_token = 0xffff; if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(nbt_netlogon_packet, &packet); } ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &packet, (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; } return cli_send_mailslot(msg_ctx, false, NBT_MAILSLOT_NTLOGON, 0, (char *)blob.data, blob.length, global_myname(), 0, domain_name, 0x1c, dc_ss); }
static bool get_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32_t *pattr) { struct xattr_DOSATTRIB dosattrib; enum ndr_err_code ndr_err; DATA_BLOB blob; ssize_t sizeret; fstring attrstr; uint32_t dosattr; if (!lp_store_dos_attributes(SNUM(conn))) { return False; } /* Don't reset pattr to zero as we may already have filename-based attributes we need to preserve. */ sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); if (sizeret == -1) { if (errno == ENOSYS #if defined(ENOTSUP) || errno == ENOTSUP) { #else ) { #endif DEBUG(1,("get_ea_dos_attribute: Cannot get attribute " "from EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno))); set_store_dos_attributes(SNUM(conn), False); } return False; } blob.data = (uint8_t *)attrstr; blob.length = sizeret; ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib, (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1,("get_ea_dos_attribute: bad ndr decode " "from EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), ndr_errstr(ndr_err))); return false; } DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n", smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex)); switch (dosattrib.version) { case 0xFFFF: dosattr = dosattrib.info.compatinfoFFFF.attrib; break; case 1: dosattr = dosattrib.info.info1.attrib; if (!null_nttime(dosattrib.info.info1.create_time)) { struct timespec create_time = nt_time_to_unix_timespec( dosattrib.info.info1.create_time); update_stat_ex_create_time(&smb_fname->st, create_time); DEBUG(10,("get_ea_dos_attribute: file %s case 1 " "set btime %s\n", smb_fname_str_dbg(smb_fname), time_to_asc(convert_timespec_to_time_t( create_time)) )); } break; case 2: dosattr = dosattrib.info.oldinfo2.attrib; /* Don't know what flags to check for this case. */ break; case 3: dosattr = dosattrib.info.info3.attrib; if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) && !null_nttime(dosattrib.info.info3.create_time)) { struct timespec create_time = nt_time_to_unix_timespec( dosattrib.info.info3.create_time); update_stat_ex_create_time(&smb_fname->st, create_time); DEBUG(10,("get_ea_dos_attribute: file %s case 3 " "set btime %s\n", smb_fname_str_dbg(smb_fname), time_to_asc(convert_timespec_to_time_t( create_time)) )); } break; default: DEBUG(1,("get_ea_dos_attribute: Badly formed DOSATTRIB on " "file %s - %s\n", smb_fname_str_dbg(smb_fname), attrstr)); return false; } if (S_ISDIR(smb_fname->st.st_ex_mode)) { dosattr |= FILE_ATTRIBUTE_DIRECTORY; } /* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */ *pattr = (uint32_t)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE)); dos_mode_debug_print(__func__, *pattr); return True; } /**************************************************************************** Set DOS attributes in an EA. Also sets the create time. ****************************************************************************/ static bool set_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32_t dosmode) { struct xattr_DOSATTRIB dosattrib; enum ndr_err_code ndr_err; DATA_BLOB blob; ZERO_STRUCT(dosattrib); ZERO_STRUCT(blob); dosattrib.version = 3; dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB| XATTR_DOSINFO_CREATE_TIME; dosattrib.info.info3.attrib = dosmode; dosattrib.info.info3.create_time = unix_timespec_to_nt_time( smb_fname->st.st_ex_btime); DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n", (unsigned int)dosmode, time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)), smb_fname_str_dbg(smb_fname) )); ndr_err = ndr_push_struct_blob( &blob, talloc_tos(), &dosattrib, (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n", ndr_errstr(ndr_err))); return false; } if (blob.data == NULL || blob.length == 0) { return false; } if (SMB_VFS_SETXATTR(conn, smb_fname->base_name, SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length, 0) == -1) { bool ret = false; bool need_close = false; files_struct *fsp = NULL; if((errno != EPERM) && (errno != EACCES)) { if (errno == ENOSYS #if defined(ENOTSUP) || errno == ENOTSUP) { #else ) { #endif DEBUG(1,("set_ea_dos_attributes: Cannot set " "attribute EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno) )); set_store_dos_attributes(SNUM(conn), False); } return false; } /* We want DOS semantics, ie allow non owner with write permission to change the bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) return false; if (!can_write_to_file(conn, smb_fname)) { return false; } /* * We need to get an open file handle to do the * metadata operation under root. */ if (!NT_STATUS_IS_OK(get_file_handle_for_metadata(conn, smb_fname, &fsp, &need_close))) { return false; } become_root(); if (SMB_VFS_FSETXATTR(fsp, SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length, 0) == 0) { ret = true; } unbecome_root(); if (need_close) { close_file(NULL, fsp, NORMAL_CLOSE); } return ret; } DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n", (unsigned int)dosmode, smb_fname_str_dbg(smb_fname))); return true; } /**************************************************************************** Change a unix mode to a dos mode for an ms dfs link. ****************************************************************************/ uint32_t dos_mode_msdfs(connection_struct *conn, const struct smb_filename *smb_fname) { uint32_t result = 0; DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname))); if (!VALID_STAT(smb_fname->st)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { const char *p = strrchr_m(smb_fname->base_name, '/'); if (p) { p++; } else { p = smb_fname->base_name; } /* Only . and .. are not hidden. */ if (p[0] == '.' && !((p[1] == '\0') || (p[1] == '.' && p[2] == '\0'))) { result |= FILE_ATTRIBUTE_HIDDEN; } } result |= dos_mode_from_sbuf(conn, smb_fname); /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & FILE_ATTRIBUTE_HIDDEN) && IS_HIDDEN_PATH(conn, smb_fname->base_name)) { result |= FILE_ATTRIBUTE_HIDDEN; } if (result == 0) { result = FILE_ATTRIBUTE_NORMAL; } result = filter_mode_by_protocol(result); /* * Add in that it is a reparse point */ result |= FILE_ATTRIBUTE_REPARSE_POINT; dos_mode_debug_print(__func__, result); return(result); }
WERROR dns_replace_records(struct dns_server *dns, TALLOC_CTX *mem_ctx, struct ldb_dn *dn, bool needs_add, const struct dnsp_DnssrvRpcRecord *records, uint16_t rec_count) { struct ldb_message_element *el; uint16_t i; int ret; struct ldb_message *msg = NULL; msg = ldb_msg_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(msg); msg->dn = dn; ret = ldb_msg_add_empty(msg, "dnsRecord", LDB_FLAG_MOD_REPLACE, &el); if (ret != LDB_SUCCESS) { return DNS_ERR(SERVER_FAILURE); } el->values = talloc_zero_array(el, struct ldb_val, rec_count); if (rec_count > 0) { W_ERROR_HAVE_NO_MEMORY(el->values); } for (i = 0; i < rec_count; i++) { static const struct dnsp_DnssrvRpcRecord zero; struct ldb_val *v = &el->values[el->num_values]; enum ndr_err_code ndr_err; if (memcmp(&records[i], &zero, sizeof(zero)) == 0) { continue; } ndr_err = ndr_push_struct_blob(v, el->values, &records[i], (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); return DNS_ERR(SERVER_FAILURE); } el->num_values++; } if (el->num_values == 0) { if (needs_add) { return WERR_OK; } /* TODO: Delete object? */ } if (needs_add) { ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); if (ret != LDB_SUCCESS) { return DNS_ERR(SERVER_FAILURE); } ret = ldb_add(dns->samdb, msg); if (ret != LDB_SUCCESS) { return DNS_ERR(SERVER_FAILURE); } return WERR_OK; } ret = ldb_modify(dns->samdb, msg); if (ret != LDB_SUCCESS) { return DNS_ERR(SERVER_FAILURE); } return WERR_OK; }
static bool set_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32_t dosmode) { struct xattr_DOSATTRIB dosattrib; enum ndr_err_code ndr_err; DATA_BLOB blob; ZERO_STRUCT(dosattrib); ZERO_STRUCT(blob); dosattrib.version = 3; dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB| XATTR_DOSINFO_CREATE_TIME; dosattrib.info.info3.attrib = dosmode; dosattrib.info.info3.create_time = unix_timespec_to_nt_time( smb_fname->st.st_ex_btime); DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n", (unsigned int)dosmode, time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)), smb_fname_str_dbg(smb_fname) )); ndr_err = ndr_push_struct_blob( &blob, talloc_tos(), &dosattrib, (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n", ndr_errstr(ndr_err))); return false; } if (blob.data == NULL || blob.length == 0) { return false; } if (SMB_VFS_SETXATTR(conn, smb_fname->base_name, SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length, 0) == -1) { bool ret = false; bool need_close = false; files_struct *fsp = NULL; if((errno != EPERM) && (errno != EACCES)) { DBG_INFO("Cannot set " "attribute EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno)); return false; } /* We want DOS semantics, ie allow non owner with write permission to change the bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) return false; if (!can_write_to_file(conn, smb_fname)) { return false; } /* * We need to get an open file handle to do the * metadata operation under root. */ if (!NT_STATUS_IS_OK(get_file_handle_for_metadata(conn, smb_fname, &fsp, &need_close))) { return false; } become_root(); if (SMB_VFS_FSETXATTR(fsp, SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length, 0) == 0) { ret = true; } unbecome_root(); if (need_close) { close_file(NULL, fsp, NORMAL_CLOSE); } return ret; } DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n", (unsigned int)dosmode, smb_fname_str_dbg(smb_fname))); return true; }
NTSTATUS vfs_default_durable_cookie(struct files_struct *fsp, TALLOC_CTX *mem_ctx, DATA_BLOB *cookie_blob) { struct connection_struct *conn = fsp->conn; enum ndr_err_code ndr_err; struct vfs_default_durable_cookie cookie; if (!lp_durable_handles(SNUM(conn))) { return NT_STATUS_NOT_SUPPORTED; } if (lp_kernel_share_modes(SNUM(conn))) { /* * We do not support durable handles * if kernel share modes (flocks) are used */ return NT_STATUS_NOT_SUPPORTED; } if (lp_kernel_oplocks(SNUM(conn))) { /* * We do not support durable handles * if kernel oplocks are used */ return NT_STATUS_NOT_SUPPORTED; } if ((fsp->current_lock_count > 0) && lp_posix_locking(fsp->conn->params)) { /* * We do not support durable handles * if the handle has posix locks. */ return NT_STATUS_NOT_SUPPORTED; } if (fsp->is_directory) { return NT_STATUS_NOT_SUPPORTED; } if (fsp->fh->fd == -1) { return NT_STATUS_NOT_SUPPORTED; } if (is_ntfs_stream_smb_fname(fsp->fsp_name)) { /* * We do not support durable handles * on streams for now. */ return NT_STATUS_NOT_SUPPORTED; } if (is_fake_file(fsp->fsp_name)) { /* * We do not support durable handles * on fake files. */ return NT_STATUS_NOT_SUPPORTED; } ZERO_STRUCT(cookie); cookie.allow_reconnect = false; cookie.id = fsp->file_id; cookie.servicepath = conn->connectpath; cookie.base_name = fsp->fsp_name->base_name; cookie.initial_allocation_size = fsp->initial_allocation_size; cookie.position_information = fsp->fh->position_information; cookie.update_write_time_triggered = fsp->update_write_time_triggered; cookie.update_write_time_on_close = fsp->update_write_time_on_close; cookie.write_time_forced = fsp->write_time_forced; cookie.close_write_time = fsp->close_write_time; cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev; cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino; cookie.stat_info.st_ex_mode = fsp->fsp_name->st.st_ex_mode; cookie.stat_info.st_ex_nlink = fsp->fsp_name->st.st_ex_nlink; cookie.stat_info.st_ex_uid = fsp->fsp_name->st.st_ex_uid; cookie.stat_info.st_ex_gid = fsp->fsp_name->st.st_ex_gid; cookie.stat_info.st_ex_rdev = fsp->fsp_name->st.st_ex_rdev; cookie.stat_info.st_ex_size = fsp->fsp_name->st.st_ex_size; cookie.stat_info.st_ex_atime = fsp->fsp_name->st.st_ex_atime; cookie.stat_info.st_ex_mtime = fsp->fsp_name->st.st_ex_mtime; cookie.stat_info.st_ex_ctime = fsp->fsp_name->st.st_ex_ctime; cookie.stat_info.st_ex_btime = fsp->fsp_name->st.st_ex_btime; cookie.stat_info.st_ex_calculated_birthtime = fsp->fsp_name->st.st_ex_calculated_birthtime; cookie.stat_info.st_ex_blksize = fsp->fsp_name->st.st_ex_blksize; cookie.stat_info.st_ex_blocks = fsp->fsp_name->st.st_ex_blocks; cookie.stat_info.st_ex_flags = fsp->fsp_name->st.st_ex_flags; cookie.stat_info.st_ex_mask = fsp->fsp_name->st.st_ex_mask; ndr_err = ndr_push_struct_blob(cookie_blob, mem_ctx, &cookie, (ndr_push_flags_fn_t)ndr_push_vfs_default_durable_cookie); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); return status; } return NT_STATUS_OK; }
static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, const struct ldb_message_element *in, TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaAttribute *out) { uint32_t i; DATA_BLOB *blobs; if (attr->attributeID_id == 0xFFFFFFFF) { return WERR_FOOBAR; } out->attid = attr->attributeID_id; out->value_ctr.num_values = in->num_values; out->value_ctr.values = talloc_array(mem_ctx, struct drsuapi_DsAttributeValue, in->num_values); W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values); blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values); W_ERROR_HAVE_NO_MEMORY(blobs); for (i=0; i < in->num_values; i++) { struct drsuapi_DsReplicaObjectIdentifier3 id3; enum ndr_err_code ndr_err; const DATA_BLOB *guid_blob, *sid_blob; struct ldb_dn *dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); out->value_ctr.values[i].blob = &blobs[i]; dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]); W_ERROR_HAVE_NO_MEMORY(dn); guid_blob = ldb_dn_get_extended_component(dn, "GUID"); ZERO_STRUCT(id3); if (guid_blob) { ndr_err = ndr_pull_struct_blob_all(guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid, (ndr_pull_flags_fn_t)ndr_pull_GUID); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } } sid_blob = ldb_dn_get_extended_component(dn, "SID"); if (sid_blob) { ndr_err = ndr_pull_struct_blob_all(sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } } id3.dn = ldb_dn_get_linearized(dn); ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } talloc_free(tmp_ctx); } return WERR_OK; }
static enum ndr_err_code get_blob_sequence_number(DATA_BLOB *blob, uint64_t *pseq) { struct ndr_pull ndr = {.data = blob->data, .data_size = blob->length}; NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pseq)); return NDR_ERR_SUCCESS; } static int share_mode_data_nofree_destructor(struct share_mode_data *d) { return -1; } static struct share_mode_data *share_mode_memcache_fetch(TALLOC_CTX *mem_ctx, const TDB_DATA id_key, DATA_BLOB *blob) { enum ndr_err_code ndr_err; struct share_mode_data *d; uint64_t sequence_number; void *ptr; struct file_id id; DATA_BLOB key; /* Ensure this is a locking_key record. */ if (id_key.dsize != sizeof(id)) { return NULL; } memcpy(&id, id_key.dptr, id_key.dsize); key = memcache_key(&id); ptr = memcache_lookup_talloc(NULL, SHARE_MODE_LOCK_CACHE, key); if (ptr == NULL) { DEBUG(10,("failed to find entry for key %s\n", file_id_string(mem_ctx, &id))); return NULL; } /* sequence number key is at start of blob. */ ndr_err = get_blob_sequence_number(blob, &sequence_number); if (ndr_err != NDR_ERR_SUCCESS) { /* Bad blob. Remove entry. */ DEBUG(10,("bad blob %u key %s\n", (unsigned int)ndr_err, file_id_string(mem_ctx, &id))); memcache_delete(NULL, SHARE_MODE_LOCK_CACHE, key); return NULL; } d = (struct share_mode_data *)ptr; if (d->sequence_number != sequence_number) { DEBUG(10,("seq changed (cached 0x%llu) (new 0x%llu) " "for key %s\n", (unsigned long long)d->sequence_number, (unsigned long long)sequence_number, file_id_string(mem_ctx, &id))); /* Cache out of date. Remove entry. */ memcache_delete(NULL, SHARE_MODE_LOCK_CACHE, key); return NULL; } /* Move onto mem_ctx. */ d = talloc_move(mem_ctx, &ptr); /* * Now we own d, prevent the cache from freeing it * when we delete the entry. */ talloc_set_destructor(d, share_mode_data_nofree_destructor); /* Remove from the cache. We own it now. */ memcache_delete(NULL, SHARE_MODE_LOCK_CACHE, key); /* And reset the destructor to none. */ talloc_set_destructor(d, NULL); DEBUG(10,("fetched entry for file %s seq 0x%llu key %s\n", d->base_name, (unsigned long long)d->sequence_number, file_id_string(mem_ctx, &id))); return d; } /******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, const TDB_DATA key, const TDB_DATA dbuf) { struct share_mode_data *d; enum ndr_err_code ndr_err; uint32_t i; DATA_BLOB blob; blob.data = dbuf.dptr; blob.length = dbuf.dsize; /* See if we already have a cached copy of this key. */ d = share_mode_memcache_fetch(mem_ctx, key, &blob); if (d != NULL) { return d; } d = talloc(mem_ctx, struct share_mode_data); if (d == NULL) { DEBUG(0, ("talloc failed\n")); goto fail; } ndr_err = ndr_pull_struct_blob_all( &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n", ndr_errstr(ndr_err))); goto fail; } /* * Initialize the values that are [skip] in the idl. The NDR code does * not initialize them. */ for (i=0; i<d->num_share_modes; i++) { struct share_mode_entry *e = &d->share_modes[i]; e->stale = false; e->lease = NULL; if (e->op_type != LEASE_OPLOCK) { continue; } if (e->lease_idx >= d->num_leases) { continue; } e->lease = &d->leases[e->lease_idx]; } d->modified = false; d->fresh = false; if (DEBUGLEVEL >= 10) { DEBUG(10, ("parse_share_modes:\n")); NDR_PRINT_DEBUG(share_mode_data, d); } return d; fail: TALLOC_FREE(d); return NULL; } /******************************************************************* Create a storable data blob from a modified share_mode_data struct. ********************************************************************/ static TDB_DATA unparse_share_modes(struct share_mode_data *d) { DATA_BLOB blob; enum ndr_err_code ndr_err; if (DEBUGLEVEL >= 10) { DEBUG(10, ("unparse_share_modes:\n")); NDR_PRINT_DEBUG(share_mode_data, d); } share_mode_memcache_delete(d); /* Update the sequence number. */ d->sequence_number += 1; remove_stale_share_mode_entries(d); if (d->num_share_modes == 0) { DEBUG(10, ("No used share mode found\n")); return make_tdb_data(NULL, 0); } ndr_err = ndr_push_struct_blob( &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { smb_panic("ndr_push_share_mode_lock failed"); } return make_tdb_data(blob.data, blob.length); }
static bool test_PACVerify(struct torture_context *tctx, struct dcerpc_pipe *p, struct cli_credentials *credentials) { NTSTATUS status; struct netr_LogonSamLogon r; union netr_LogonLevel logon; union netr_Validation validation; uint8_t authoritative; struct netr_Authenticator return_authenticator; struct netr_GenericInfo generic; struct netr_Authenticator auth, auth2; struct netlogon_creds_CredentialState *creds; struct gensec_security *gensec_client_context; struct gensec_security *gensec_server_context; DATA_BLOB client_to_server, server_to_client, pac_wrapped, payload; struct PAC_Validate pac_wrapped_struct; enum ndr_err_code ndr_err; struct auth_session_info *session_info; char *tmp_dir; TALLOC_CTX *tmp_ctx = talloc_new(tctx); torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed"); if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, credentials, SEC_CHAN_BDC, &creds)) { return false; } status = torture_temp_dir(tctx, "PACVerify", &tmp_dir); torture_assert_ntstatus_ok(tctx, status, "torture_temp_dir failed"); status = gensec_client_start(tctx, &gensec_client_context, tctx->ev, lp_gensec_settings(tctx, tctx->lp_ctx)); torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed"); status = gensec_set_target_hostname(gensec_client_context, TEST_MACHINE_NAME); status = gensec_set_credentials(gensec_client_context, cmdline_credentials); torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed"); status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI"); torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed"); status = gensec_server_start(tctx, tctx->ev, lp_gensec_settings(tctx, tctx->lp_ctx), NULL, &gensec_server_context); torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed"); status = gensec_set_credentials(gensec_server_context, credentials); torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed"); status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI"); torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed"); server_to_client = data_blob(NULL, 0); do { /* Do a client-server update dance */ status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { ; torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed"); } status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { ; torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed"); } if (NT_STATUS_IS_OK(status)) { break; } } while (1); /* Extract the PAC using Samba's code */ status = gensec_session_info(gensec_server_context, &session_info); torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed"); pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; pac_wrapped_struct.ChecksumAndSignature = payload = data_blob_talloc(tmp_ctx, NULL, pac_wrapped_struct.ChecksumLength + pac_wrapped_struct.SignatureLength); memcpy(&payload.data[0], session_info->server_info->pac_srv_sig.signature.data, pac_wrapped_struct.ChecksumLength); memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], session_info->server_info->pac_kdc_sig.signature.data, pac_wrapped_struct.SignatureLength); ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, (ndr_push_flags_fn_t)ndr_push_PAC_Validate); torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; /* Validate it over the netlogon pipe */ generic.identity_info.parameter_control = 0; generic.identity_info.logon_id_high = 0; generic.identity_info.logon_id_low = 0; generic.identity_info.domain_name.string = session_info->server_info->domain_name; generic.identity_info.account_name.string = session_info->server_info->account_name; generic.identity_info.workstation.string = TEST_MACHINE_NAME; generic.package_name.string = "Kerberos"; logon.generic = &generic; ZERO_STRUCT(auth2); netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon = &logon; r.in.logon_level = NetlogonGenericInformation; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computer_name = cli_credentials_get_workstation(credentials); r.in.validation_level = NetlogonValidationGenericInfo2; r.out.validation = &validation; r.out.authoritative = &authoritative; r.out.return_authenticator = &return_authenticator; status = dcerpc_netr_LogonSamLogon(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */ generic.data[generic.length-1]++; logon.generic = &generic; ZERO_STRUCT(auth2); netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; r.in.logon = &logon; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computer_name = cli_credentials_get_workstation(credentials); r.in.validation_level = NetlogonValidationGenericInfo2; status = dcerpc_netr_LogonSamLogon(p, tctx, &r); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed"); torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */ generic.length--; logon.generic = &generic; ZERO_STRUCT(auth2); netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; r.in.logon = &logon; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computer_name = cli_credentials_get_workstation(credentials); r.in.validation_level = NetlogonValidationGenericInfo2; status = dcerpc_netr_LogonSamLogon(p, tctx, &r); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed"); torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; /* Break the SignatureType */ pac_wrapped_struct.SignatureType++; pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; pac_wrapped_struct.ChecksumAndSignature = payload = data_blob_talloc(tmp_ctx, NULL, pac_wrapped_struct.ChecksumLength + pac_wrapped_struct.SignatureLength); memcpy(&payload.data[0], session_info->server_info->pac_srv_sig.signature.data, pac_wrapped_struct.ChecksumLength); memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], session_info->server_info->pac_kdc_sig.signature.data, pac_wrapped_struct.SignatureLength); ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, (ndr_push_flags_fn_t)ndr_push_PAC_Validate); torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; logon.generic = &generic; ZERO_STRUCT(auth2); netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; r.in.logon = &logon; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computer_name = cli_credentials_get_workstation(credentials); r.in.validation_level = NetlogonValidationGenericInfo2; status = dcerpc_netr_LogonSamLogon(p, tctx, &r); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed"); torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; pac_wrapped_struct.ChecksumAndSignature = payload = data_blob_talloc(tmp_ctx, NULL, pac_wrapped_struct.ChecksumLength + pac_wrapped_struct.SignatureLength); memcpy(&payload.data[0], session_info->server_info->pac_srv_sig.signature.data, pac_wrapped_struct.ChecksumLength); memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], session_info->server_info->pac_kdc_sig.signature.data, pac_wrapped_struct.SignatureLength); /* Break the signature length */ pac_wrapped_struct.SignatureLength++; ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, (ndr_push_flags_fn_t)ndr_push_PAC_Validate); torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); generic.length = pac_wrapped.length; generic.data = pac_wrapped.data; logon.generic = &generic; ZERO_STRUCT(auth2); netlogon_creds_client_authenticator(creds, &auth); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = NetlogonGenericInformation; r.in.logon = &logon; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.computer_name = cli_credentials_get_workstation(credentials); r.in.validation_level = NetlogonValidationGenericInfo2; status = dcerpc_netr_LogonSamLogon(p, tctx, &r); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed"); torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); return true; }
NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, TALLOC_CTX *out_mem_ctx, const DATA_BLOB request, DATA_BLOB *reply) { DATA_BLOB struct_blob; uint32_t neg_flags = 0; uint32_t ntlmssp_command, chal_flags; uint8_t cryptkey[8]; const char *target_name; NTSTATUS status; /* parse the NTLMSSP packet */ #if 0 file_save("ntlmssp_negotiate.dat", request.data, request.length); #endif if (request.length) { if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd", "NTLMSSP", &ntlmssp_command, &neg_flags)) { DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n", (unsigned int)request.length)); dump_data(2, request.data, request.length); return NT_STATUS_INVALID_PARAMETER; } debug_ntlmssp_flags(neg_flags); if (DEBUGLEVEL >= 10) { struct NEGOTIATE_MESSAGE *negotiate = talloc( ntlmssp_state, struct NEGOTIATE_MESSAGE); if (negotiate != NULL) { status = ntlmssp_pull_NEGOTIATE_MESSAGE( &request, negotiate, negotiate); if (NT_STATUS_IS_OK(status)) { NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE, negotiate); } TALLOC_FREE(negotiate); } } } ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, ntlmssp_state->allow_lm_key); /* Ask our caller what challenge they would like in the packet */ status = ntlmssp_state->get_challenge(ntlmssp_state, cryptkey); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("ntlmssp_server_negotiate: backend doesn't give a challenge: %s\n", nt_errstr(status))); return status; } /* Check if we may set the challenge */ if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) { ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; } /* The flags we send back are not just the negotiated flags, * they are also 'what is in this packet'. Therfore, we * operate on 'chal_flags' from here on */ chal_flags = ntlmssp_state->neg_flags; /* get the right name to fill in as 'target' */ target_name = ntlmssp_target_name(ntlmssp_state, neg_flags, &chal_flags); if (target_name == NULL) return NT_STATUS_INVALID_PARAMETER; ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8); ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state, cryptkey, 8); /* This creates the 'blob' of names that appears at the end of the packet */ if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) { status = msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa", MsvAvNbDomainName, target_name, MsvAvNbComputerName, ntlmssp_state->server.netbios_name, MsvAvDnsDomainName, ntlmssp_state->server.dns_domain, MsvAvDnsComputerName, ntlmssp_state->server.dns_name, MsvAvEOL, ""); if (!NT_STATUS_IS_OK(status)) { return status; } } else { struct_blob = data_blob_null; } { /* Marshal the packet in the right format, be it unicode or ASCII */ const char *gen_string; DATA_BLOB version_blob = data_blob_null; if (chal_flags & NTLMSSP_NEGOTIATE_VERSION) { enum ndr_err_code err; struct ntlmssp_VERSION vers; /* "What Windows returns" as a version number. */ ZERO_STRUCT(vers); vers.ProductMajorVersion = NTLMSSP_WINDOWS_MAJOR_VERSION_6; vers.ProductMinorVersion = NTLMSSP_WINDOWS_MINOR_VERSION_1; vers.ProductBuild = 0; vers.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3; err = ndr_push_struct_blob(&version_blob, ntlmssp_state, &vers, (ndr_push_flags_fn_t)ndr_push_ntlmssp_VERSION); if (!NDR_ERR_CODE_IS_SUCCESS(err)) { data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; } } if (ntlmssp_state->unicode) { gen_string = "CdUdbddBb"; } else { gen_string = "CdAdbddBb"; } status = msrpc_gen(out_mem_ctx, reply, gen_string, "NTLMSSP", NTLMSSP_CHALLENGE, target_name, chal_flags, cryptkey, 8, 0, 0, struct_blob.data, struct_blob.length, version_blob.data, version_blob.length); if (!NT_STATUS_IS_OK(status)) { data_blob_free(&version_blob); data_blob_free(&struct_blob); return status; } data_blob_free(&version_blob); if (DEBUGLEVEL >= 10) { struct CHALLENGE_MESSAGE *challenge = talloc( ntlmssp_state, struct CHALLENGE_MESSAGE); if (challenge != NULL) { challenge->NegotiateFlags = chal_flags; status = ntlmssp_pull_CHALLENGE_MESSAGE( reply, challenge, challenge); if (NT_STATUS_IS_OK(status)) { NDR_PRINT_DEBUG(CHALLENGE_MESSAGE, challenge); } TALLOC_FREE(challenge); } } } data_blob_free(&struct_blob); ntlmssp_state->expected_state = NTLMSSP_AUTH; return NT_STATUS_MORE_PROCESSING_REQUIRED; }
static WERROR dns_tsig_compute_mac(TALLOC_CTX *mem_ctx, struct dns_request_state *state, struct dns_name_packet *packet, struct dns_server_tkey *tkey, time_t current_time, DATA_BLOB *_psig) { NTSTATUS status; enum ndr_err_code ndr_err; DATA_BLOB packet_blob, tsig_blob, sig; uint8_t *buffer = NULL; uint8_t *p = NULL; size_t buffer_len = 0; struct dns_fake_tsig_rec *check_rec = talloc_zero(mem_ctx, struct dns_fake_tsig_rec); size_t mac_size = 0; if (check_rec == NULL) { return WERR_NOT_ENOUGH_MEMORY; } /* first build and verify check packet */ check_rec->name = talloc_strdup(check_rec, tkey->name); if (check_rec->name == NULL) { return WERR_NOT_ENOUGH_MEMORY; } check_rec->rr_class = DNS_QCLASS_ANY; check_rec->ttl = 0; check_rec->algorithm_name = talloc_strdup(check_rec, tkey->algorithm); if (check_rec->algorithm_name == NULL) { return WERR_NOT_ENOUGH_MEMORY; } check_rec->time_prefix = 0; check_rec->time = current_time; check_rec->fudge = 300; check_rec->error = state->tsig_error; check_rec->other_size = 0; check_rec->other_data = NULL; ndr_err = ndr_push_struct_blob(&packet_blob, mem_ctx, packet, (ndr_push_flags_fn_t)ndr_push_dns_name_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("Failed to push packet: %s!\n", ndr_errstr(ndr_err))); return DNS_ERR(SERVER_FAILURE); } ndr_err = ndr_push_struct_blob(&tsig_blob, mem_ctx, check_rec, (ndr_push_flags_fn_t)ndr_push_dns_fake_tsig_rec); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("Failed to push packet: %s!\n", ndr_errstr(ndr_err))); return DNS_ERR(SERVER_FAILURE); } if (state->tsig != NULL) { mac_size = state->tsig->rdata.tsig_record.mac_size; } buffer_len = mac_size; buffer_len += packet_blob.length; if (buffer_len < packet_blob.length) { return WERR_INVALID_PARAMETER; } buffer_len += tsig_blob.length; if (buffer_len < tsig_blob.length) { return WERR_INVALID_PARAMETER; } buffer = talloc_zero_array(mem_ctx, uint8_t, buffer_len); if (buffer == NULL) { return WERR_NOT_ENOUGH_MEMORY; } p = buffer; /* * RFC 2845 "4.2 TSIG on Answers", how to lay out the buffer * that we're going to sign: * 1. MAC of request (if present) * 2. Outgoing packet * 3. TSIG record */ if (mac_size > 0) { memcpy(p, state->tsig->rdata.tsig_record.mac, mac_size); p += mac_size; } memcpy(p, packet_blob.data, packet_blob.length); p += packet_blob.length; memcpy(p, tsig_blob.data, tsig_blob.length); status = gensec_sign_packet(tkey->gensec, mem_ctx, buffer, buffer_len, buffer, buffer_len, &sig); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } *_psig = sig; return WERR_OK; }
static WERROR sptr_PrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, const char *value_name, union spoolss_PrinterData *r, enum winreg_Type *type) { struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx); if (strcmp("W3SvcInstalled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("BeepEnabled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("EventLog", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopup", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopupToComputer", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("MajorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 3; return WERR_OK; } else if (strcmp("MinorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("DefaultSpoolDirectory", value_name) == 0) { *type = REG_SZ; r->string = "C:\\PRINTERS"; return WERR_OK; } else if (strcmp("Architecture", value_name) == 0) { *type = REG_SZ; r->string = SPOOLSS_ARCHITECTURE_NT_X86; return WERR_OK; } else if (strcmp("DsPresent", value_name) == 0) { *type = REG_DWORD; r->value = 1; return WERR_OK; } else if (strcmp("OSVersion", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersion os; os.major = server_info->version_major; os.minor = server_info->version_minor; os.build = server_info->version_build; os.extra_string = ""; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("OSVersionEx", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersionEx os_ex; os_ex.major = server_info->version_major; os_ex.minor = server_info->version_minor; os_ex.build = server_info->version_build; os_ex.extra_string = ""; os_ex.service_pack_major= 0; os_ex.service_pack_minor= 0; os_ex.suite_mask = 0; os_ex.product_type = 0; os_ex.reserved = 0; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("DNSMachineName", value_name) == 0) { const char *dnsdomain = lpcfg_dnsdomain(server->ntptr->lp_ctx); if (dnsdomain == NULL) return WERR_INVALID_PARAM; *type = REG_SZ; r->string = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(server->ntptr->lp_ctx), dnsdomain); W_ERROR_HAVE_NO_MEMORY(r->string); return WERR_OK; } return WERR_INVALID_PARAM; }
krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx, struct PAC_DATA *pac_data, krb5_context context, const krb5_keyblock *krbtgt_keyblock, const krb5_keyblock *service_keyblock, DATA_BLOB *pac) { NTSTATUS nt_status; krb5_error_code ret; enum ndr_err_code ndr_err; DATA_BLOB zero_blob = data_blob(NULL, 0); DATA_BLOB tmp_blob = data_blob(NULL, 0); struct PAC_SIGNATURE_DATA *kdc_checksum = NULL; struct PAC_SIGNATURE_DATA *srv_checksum = NULL; int i; /* First, just get the keytypes filled in (and lengths right, eventually) */ for (i=0; i < pac_data->num_buffers; i++) { if (pac_data->buffers[i].type != PAC_TYPE_KDC_CHECKSUM) { continue; } kdc_checksum = &pac_data->buffers[i].info->kdc_cksum, ret = smb_krb5_make_pac_checksum(mem_ctx, &zero_blob, context, krbtgt_keyblock, &kdc_checksum->type, &kdc_checksum->signature); if (ret) { DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); talloc_free(pac_data); return ret; } } for (i=0; i < pac_data->num_buffers; i++) { if (pac_data->buffers[i].type != PAC_TYPE_SRV_CHECKSUM) { continue; } srv_checksum = &pac_data->buffers[i].info->srv_cksum; ret = smb_krb5_make_pac_checksum(mem_ctx, &zero_blob, context, service_keyblock, &srv_checksum->type, &srv_checksum->signature); if (ret) { DEBUG(2, ("making service PAC checksum failed: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); talloc_free(pac_data); return ret; } } if (!kdc_checksum) { DEBUG(2, ("Invalid PAC constructed for signing, no KDC checksum present!")); return EINVAL; } if (!srv_checksum) { DEBUG(2, ("Invalid PAC constructed for signing, no SRV checksum present!")); return EINVAL; } /* But wipe out the actual signatures */ memset(kdc_checksum->signature.data, '\0', kdc_checksum->signature.length); memset(srv_checksum->signature.data, '\0', srv_checksum->signature.length); ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data, (ndr_push_flags_fn_t)ndr_push_PAC_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { nt_status = ndr_map_error2ntstatus(ndr_err); DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status))); talloc_free(pac_data); return EINVAL; } /* Then sign the result of the previous push, where the sig was zero'ed out */ ret = smb_krb5_make_pac_checksum(mem_ctx, &tmp_blob, context, service_keyblock, &srv_checksum->type, &srv_checksum->signature); /* Then sign Server checksum */ ret = smb_krb5_make_pac_checksum(mem_ctx, &srv_checksum->signature, context, krbtgt_keyblock, &kdc_checksum->type, &kdc_checksum->signature); if (ret) { DEBUG(2, ("making krbtgt PAC checksum failed: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); talloc_free(pac_data); return ret; } /* And push it out again, this time to the world. This relies on determanistic pointer values */ ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data, (ndr_push_flags_fn_t)ndr_push_PAC_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { nt_status = ndr_map_error2ntstatus(ndr_err); DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status))); talloc_free(pac_data); return EINVAL; } *pac = tmp_blob; return ret; }
NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, struct PAC_DATA **pac_data_out, DATA_BLOB blob, krb5_context context, const krb5_keyblock *krbtgt_keyblock, const krb5_keyblock *service_keyblock, krb5_const_principal client_principal, time_t tgs_authtime, krb5_error_code *k5ret) { krb5_error_code ret; NTSTATUS status; enum ndr_err_code ndr_err; struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL; struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL; struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL; struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL; struct PAC_LOGON_INFO *logon_info = NULL; struct PAC_LOGON_NAME *logon_name = NULL; struct PAC_DATA *pac_data; struct PAC_DATA_RAW *pac_data_raw; DATA_BLOB *srv_sig_blob = NULL; DATA_BLOB *kdc_sig_blob = NULL; DATA_BLOB modified_pac_blob; NTTIME tgs_authtime_nttime; krb5_principal client_principal_pac; int i; krb5_clear_error_message(context); if (k5ret) { *k5ret = KRB5_PARSE_MALFORMED; } pac_data = talloc(mem_ctx, struct PAC_DATA); pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW); kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA); srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA); if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) { if (k5ret) { *k5ret = ENOMEM; } return NT_STATUS_NO_MEMORY; } ndr_err = ndr_pull_struct_blob(&blob, pac_data, iconv_convenience, pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the PAC: %s\n", nt_errstr(status))); return status; } if (pac_data->num_buffers < 4) { /* we need logon_ingo, service_key and kdc_key */ DEBUG(0,("less than 4 PAC buffers\n")); return NT_STATUS_INVALID_PARAMETER; } ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw, iconv_convenience, pac_data_raw, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the PAC: %s\n", nt_errstr(status))); return status; } if (pac_data_raw->num_buffers < 4) { /* we need logon_ingo, service_key and kdc_key */ DEBUG(0,("less than 4 PAC buffers\n")); return NT_STATUS_INVALID_PARAMETER; } if (pac_data->num_buffers != pac_data_raw->num_buffers) { /* we need logon_ingo, service_key and kdc_key */ DEBUG(0,("misparse! PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n", pac_data->num_buffers, pac_data_raw->num_buffers)); return NT_STATUS_INVALID_PARAMETER; } for (i=0; i < pac_data->num_buffers; i++) { if (pac_data->buffers[i].type != pac_data_raw->buffers[i].type) { DEBUG(0,("misparse! PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n", i, pac_data->buffers[i].type, pac_data->buffers[i].type)); return NT_STATUS_INVALID_PARAMETER; } switch (pac_data->buffers[i].type) { case PAC_TYPE_LOGON_INFO: if (!pac_data->buffers[i].info) { break; } logon_info = pac_data->buffers[i].info->logon_info.info; break; case PAC_TYPE_SRV_CHECKSUM: if (!pac_data->buffers[i].info) { break; } srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum; srv_sig_blob = &pac_data_raw->buffers[i].info->remaining; break; case PAC_TYPE_KDC_CHECKSUM: if (!pac_data->buffers[i].info) { break; } kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum; kdc_sig_blob = &pac_data_raw->buffers[i].info->remaining; break; case PAC_TYPE_LOGON_NAME: logon_name = &pac_data->buffers[i].info->logon_name; break; default: break; } } if (!logon_info) { DEBUG(0,("PAC no logon_info\n")); return NT_STATUS_INVALID_PARAMETER; } if (!logon_name) { DEBUG(0,("PAC no logon_name\n")); return NT_STATUS_INVALID_PARAMETER; } if (!srv_sig_ptr || !srv_sig_blob) { DEBUG(0,("PAC no srv_key\n")); return NT_STATUS_INVALID_PARAMETER; } if (!kdc_sig_ptr || !kdc_sig_blob) { DEBUG(0,("PAC no kdc_key\n")); return NT_STATUS_INVALID_PARAMETER; } /* Find and zero out the signatures, as required by the signing algorithm */ /* We find the data blobs above, now we parse them to get at the exact portion we should zero */ ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe, iconv_convenience, kdc_sig_wipe, (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the KDC signature: %s\n", nt_errstr(status))); return status; } ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe, iconv_convenience, srv_sig_wipe, (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't parse the SRV signature: %s\n", nt_errstr(status))); return status; } /* Now zero the decoded structure */ memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length); memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length); /* and reencode, back into the same place it came from */ ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw, iconv_convenience, kdc_sig_wipe, (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't repack the KDC signature: %s\n", nt_errstr(status))); return status; } ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw, iconv_convenience, srv_sig_wipe, (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't repack the SRV signature: %s\n", nt_errstr(status))); return status; } /* push out the whole structure, but now with zero'ed signatures */ ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw, iconv_convenience, pac_data_raw, (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(0,("can't repack the RAW PAC: %s\n", nt_errstr(status))); return status; } /* verify by service_key */ ret = check_pac_checksum(mem_ctx, modified_pac_blob, srv_sig_ptr, context, service_keyblock); if (ret) { DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); if (k5ret) { *k5ret = ret; } return NT_STATUS_ACCESS_DENIED; } if (krbtgt_keyblock) { ret = check_pac_checksum(mem_ctx, srv_sig_ptr->signature, kdc_sig_ptr, context, krbtgt_keyblock); if (ret) { DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); if (k5ret) { *k5ret = ret; } return NT_STATUS_ACCESS_DENIED; } } /* Convert to NT time, so as not to loose accuracy in comparison */ unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); if (tgs_authtime_nttime != logon_name->logon_time) { DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n")); DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time))); DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime))); return NT_STATUS_ACCESS_DENIED; } ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM, &client_principal_pac); if (ret) { DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n", logon_name->account_name, smb_get_krb5_error_message(context, ret, mem_ctx))); if (k5ret) { *k5ret = ret; } return NT_STATUS_INVALID_PARAMETER; } if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) { DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n", logon_name->account_name)); return NT_STATUS_ACCESS_DENIED; } #if 0 if (strcasecmp(logon_info->info3.base.account_name.string, "Administrator")== 0) { file_save("tmp_pac_data-admin.dat",blob.data,blob.length); } #endif DEBUG(3,("Found account name from PAC: %s [%s]\n", logon_info->info3.base.account_name.string, logon_info->info3.base.full_name.string)); *pac_data_out = pac_data; return NT_STATUS_OK; }
NTSTATUS _eventlog_ReadEventLogW(struct pipes_struct *p, struct eventlog_ReadEventLogW *r) { EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle ); uint32_t num_records_read = 0; int bytes_left, record_number; uint32_t elog_read_type, elog_read_dir; if (!info) { return NT_STATUS_INVALID_HANDLE; } info->flags = r->in.flags; bytes_left = r->in.number_of_bytes; if (!info->etdb) { return NT_STATUS_ACCESS_DENIED; } /* check for valid flags. Can't use the sequential and seek flags together */ elog_read_type = r->in.flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ); elog_read_dir = r->in.flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ); if (r->in.flags == 0 || elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) || elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ)) { DEBUG(3,("_eventlog_ReadEventLogW: " "Invalid flags [0x%08x] for ReadEventLog\n", r->in.flags)); return NT_STATUS_INVALID_PARAMETER; } /* a sequential read should ignore the offset */ if (elog_read_type & EVENTLOG_SEQUENTIAL_READ) { record_number = info->current_record; } else { record_number = r->in.offset; } if (r->in.number_of_bytes == 0) { struct EVENTLOGRECORD *e; e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb), record_number); if (!e) { return NT_STATUS_END_OF_FILE; } *r->out.real_size = e->Length; return NT_STATUS_BUFFER_TOO_SMALL; } while (bytes_left > 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct EVENTLOGRECORD *e; e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb), record_number); if (!e) { break; } ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, e, (ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(EVENTLOGRECORD, e); } if (blob.length > r->in.number_of_bytes) { *r->out.real_size = blob.length; return NT_STATUS_BUFFER_TOO_SMALL; } if (*r->out.sent_size + blob.length > r->in.number_of_bytes) { break; } bytes_left -= blob.length; if (info->flags & EVENTLOG_FORWARDS_READ) { record_number++; } else { record_number--; } /* update the eventlog record pointer */ info->current_record = record_number; memcpy(&r->out.data[*(r->out.sent_size)], blob.data, blob.length); *(r->out.sent_size) += blob.length; num_records_read++; } if (r->in.offset == 0 && record_number == 0 && *r->out.sent_size == 0) { return NT_STATUS_END_OF_FILE; } return NT_STATUS_OK; }
static int ipa_cldap_encode_netlogon(char *hostname, char *domain, char *guid, char *sid, char *name, uint32_t ntver, struct berval *reply) { struct NETLOGON_SAM_LOGON_RESPONSE_EX *nlr; enum ndr_err_code ndr_err; DATA_BLOB blob; char *pdc_name; char *p; int ret; nlr = talloc_zero(NULL, struct NETLOGON_SAM_LOGON_RESPONSE_EX); if (!nlr) { return ENOMEM; } if (!(ntver & NETLOGON_NT_VERSION_5EX)) { ret = EINVAL; goto done; } nlr->command = LOGON_SAM_LOGON_RESPONSE_EX; /* nlr->sbz */ nlr->server_type = DS_SERVER_PDC | DS_SERVER_GC | DS_SERVER_LDAP | DS_SERVER_DS | DS_SERVER_KDC | DS_SERVER_TIMESERV | DS_SERVER_CLOSEST | DS_SERVER_WRITABLE | DS_SERVER_GOOD_TIMESERV; string_to_guid(guid, &nlr->domain_uuid); nlr->forest = domain; nlr->dns_domain = domain; nlr->pdc_dns_name = talloc_asprintf(nlr, "%s.%s", hostname, domain); if (!nlr->pdc_dns_name) { ret = ENOMEM; goto done; } nlr->domain_name = name; pdc_name = talloc_asprintf(nlr, "\\\\%s", hostname); for (p = pdc_name; *p; p++) { *p = toupper(*p); } nlr->pdc_name = pdc_name; nlr->user_name = ""; nlr->server_site = "Default-First-Site-Name"; nlr->client_site = "Default-First-Site-Name"; /* nlr->sockaddr_size (filled in by ndr_push) */ nlr->sockaddr.sockaddr_family = 2; nlr->sockaddr.pdc_ip = "127.0.0.1"; nlr->sockaddr.remaining.length = 8; nlr->sockaddr.remaining.data = talloc_zero_size(nlr, 8); /* nlr->next_closest_site */ nlr->nt_version = NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_1; nlr->lmnt_token = 0xFFFF; nlr->lm20_token = 0xFFFF; ndr_err = ndr_push_struct_blob(&blob, nlr, nlr, NETLOGON_SAM_LOGON_RESPONSE_EX_pusher); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ret = EFAULT; goto done; } reply->bv_val = malloc(blob.length); if (!reply->bv_val) { ret = ENOMEM; goto done; } memcpy(reply->bv_val, blob.data, blob.length); reply->bv_len = blob.length; ret = 0; done: talloc_free(nlr); return ret; }