/******************************************************************* Parse a byte stream into a secdesc ********************************************************************/ NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len, struct security_descriptor **psecdesc) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct security_descriptor *result; if ((data == NULL) || (len == 0)) { return NT_STATUS_INVALID_PARAMETER; } result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor); if (result == NULL) { return NT_STATUS_NO_MEMORY; } blob = data_blob_const(data, len); ndr_err = ndr_pull_struct_blob( &blob, result, result, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n", ndr_errstr(ndr_err))); TALLOC_FREE(result); return ndr_map_error2ntstatus(ndr_err);; } *psecdesc = result; return NT_STATUS_OK; }
static struct netlogon_creds_CredentialState * secrets_fetch_local_schannel_creds(TALLOC_CTX *mem_ctx) { struct netlogon_creds_CredentialState *creds; enum ndr_err_code ndr_err; DATA_BLOB blob; blob.data = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, &blob.length); if (blob.data == NULL) { DEBUG(10, ("secrets_fetch failed\n")); return NULL; } creds = talloc(mem_ctx, struct netlogon_creds_CredentialState); if (creds == NULL) { DEBUG(10, ("talloc failed\n")); SAFE_FREE(blob.data); return NULL; } ndr_err = ndr_pull_struct_blob( &blob, creds, creds, (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState); SAFE_FREE(blob.data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(10, ("ndr_pull_netlogon_creds_CredentialState failed: " "%s\n", ndr_errstr(ndr_err))); TALLOC_FREE(creds); return NULL; } return creds; }
static void dump_printer(TALLOC_CTX *mem_ctx, const char *key_name, unsigned char *data, size_t length) { enum ndr_err_code ndr_err; DATA_BLOB blob; char *s; struct ntprinting_printer r; printf("found printer: %s\n", key_name); blob = data_blob_const(data, length); ZERO_STRUCT(r); ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { d_fprintf(stderr, _("printer pull failed: %s\n"), ndr_errstr(ndr_err)); return; } s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r); if (s) { printf("%s\n", s); } }
static bool leases_db_key(TALLOC_CTX *mem_ctx, const struct GUID *client_guid, const struct smb2_lease_key *lease_key, TDB_DATA *key) { struct leases_db_key db_key = { .client_guid = *client_guid, .lease_key = *lease_key }; DATA_BLOB blob; enum ndr_err_code ndr_err; if (DEBUGLEVEL >= 10) { DEBUG(10, ("%s:\n", __func__)); NDR_PRINT_DEBUG(leases_db_key, &db_key); } ndr_err = ndr_push_struct_blob( &blob, mem_ctx, &db_key, (ndr_push_flags_fn_t)ndr_push_leases_db_key); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(10, ("%s: ndr_push_struct_blob_failed: %s\n", __func__, ndr_errstr(ndr_err))); return false; } *key = make_tdb_data(blob.data, blob.length); return true; }
static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob) { struct xattr_NTACL xacl; struct security_descriptor_hash sd_hs; enum ndr_err_code ndr_err; TALLOC_CTX *ctx = talloc_tos(); ZERO_STRUCT(xacl); ZERO_STRUCT(sd_hs); xacl.version = 2; xacl.info.sd_hs = &sd_hs; xacl.info.sd_hs->sd = CONST_DISCARD(struct security_descriptor *, psd); memset(&xacl.info.sd_hs->hash[0], '\0', 16); ndr_err = ndr_push_struct_blob( pblob, ctx, NULL, &xacl, (ndr_push_flags_fn_t)ndr_push_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n", ndr_errstr(ndr_err))); return ndr_map_error2ntstatus(ndr_err);; } return NT_STATUS_OK; }
static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob, uint16_t hash_type, uint8_t hash[XATTR_SD_HASH_SIZE]) { struct xattr_NTACL xacl; struct security_descriptor_hash_v3 sd_hs3; enum ndr_err_code ndr_err; TALLOC_CTX *ctx = talloc_tos(); ZERO_STRUCT(xacl); ZERO_STRUCT(sd_hs3); xacl.version = 3; xacl.info.sd_hs3 = &sd_hs3; xacl.info.sd_hs3->sd = discard_const_p(struct security_descriptor, psd); xacl.info.sd_hs3->hash_type = hash_type; memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE); ndr_err = ndr_push_struct_blob( pblob, ctx, &xacl, (ndr_push_flags_fn_t)ndr_push_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n", ndr_errstr(ndr_err))); return ndr_map_error2ntstatus(ndr_err); } return NT_STATUS_OK; }
NTSTATUS printing_tdb_migrate_form(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct ntprinting_form r; struct spoolss_AddFormInfo1 f1; DATA_BLOB blob; WERROR result; blob = data_blob_const(data, length); ZERO_STRUCT(r); ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("Form pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } /* Don't migrate builtin forms */ if (r.flag == SPOOLSS_FORM_BUILTIN) { return NT_STATUS_OK; } DEBUG(2, ("Migrating Form: %s\n", key_name)); f1.form_name = key_name; f1.flags = r.flag; f1.size.width = r.width; f1.size.height = r.length; f1.area.top = r.top; f1.area.right = r.right; f1.area.bottom = r.bottom; f1.area.left = r.left; result = winreg_printer_addform1(mem_ctx, b, &f1); if (W_ERROR_EQUAL(result, WERR_FILE_EXISTS)) { /* Don't migrate form if it already exists. */ result = WERR_OK; } if (!W_ERROR_IS_OK(result)) { return werror_to_ntstatus(result); } return NT_STATUS_OK; }
static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, const TDB_DATA dbuf) { struct share_mode_data *d; enum ndr_err_code ndr_err; uint32_t i; DATA_BLOB blob; d = talloc(mem_ctx, struct share_mode_data); if (d == NULL) { DEBUG(0, ("talloc failed\n")); goto fail; } blob.data = dbuf.dptr; blob.length = dbuf.dsize; 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; }
static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, struct security_descriptor **ppdesc, uint16_t *p_hash_type, uint8_t hash[XATTR_SD_HASH_SIZE]) { TALLOC_CTX *ctx = talloc_tos(); struct xattr_NTACL xacl; enum ndr_err_code ndr_err; size_t sd_size; ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl, (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n", ndr_errstr(ndr_err))); return ndr_map_error2ntstatus(ndr_err);; } switch (xacl.version) { case 2: *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE, xacl.info.sd_hs2->sd->owner_sid, xacl.info.sd_hs2->sd->group_sid, xacl.info.sd_hs2->sd->sacl, xacl.info.sd_hs2->sd->dacl, &sd_size); /* No hash - null out. */ *p_hash_type = XATTR_SD_HASH_TYPE_NONE; memset(hash, '\0', XATTR_SD_HASH_SIZE); break; case 3: *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE, xacl.info.sd_hs3->sd->owner_sid, xacl.info.sd_hs3->sd->group_sid, xacl.info.sd_hs3->sd->sacl, xacl.info.sd_hs3->sd->dacl, &sd_size); *p_hash_type = xacl.info.sd_hs3->hash_type; /* Current version 3. */ memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE); break; default: return NT_STATUS_REVISION_MISMATCH; } TALLOC_FREE(xacl.info.sd); return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; }
static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl) { enum ndr_err_code ndr_err; DATA_BLOB blob; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl, (ndr_push_flags_fn_t)ndr_push_nfs4acl); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0, ("ndr_push_acl_t failed: %s\n", ndr_errstr(ndr_err))); return data_blob_null; } return blob; }
struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx, const struct auth_session_info *src) { struct auth_session_info *dst; DATA_BLOB blob; enum ndr_err_code ndr_err; ndr_err = ndr_push_struct_blob( &blob, talloc_tos(), src, (ndr_push_flags_fn_t)ndr_push_auth_session_info); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: " "%s\n", ndr_errstr(ndr_err))); return NULL; } dst = talloc(mem_ctx, struct auth_session_info); if (dst == NULL) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(blob.data); return NULL; } ndr_err = ndr_pull_struct_blob( &blob, dst, dst, (ndr_pull_flags_fn_t)ndr_pull_auth_session_info); TALLOC_FREE(blob.data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: " "%s\n", ndr_errstr(ndr_err))); TALLOC_FREE(dst); return NULL; } return dst; }
static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) { enum ndr_err_code ndr_err; struct nfs4acl *acl = talloc(mem_ctx, struct nfs4acl); if (!acl) { errno = ENOMEM; return NULL; } ndr_err = ndr_pull_struct_blob(blob, acl, acl, (ndr_pull_flags_fn_t)ndr_pull_nfs4acl); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0, ("ndr_pull_acl_t failed: %s\n", ndr_errstr(ndr_err))); TALLOC_FREE(acl); return NULL; } return acl; }
static bool secrets_store_local_schannel_creds( const struct netlogon_creds_CredentialState *creds) { DATA_BLOB blob; enum ndr_err_code ndr_err; bool ret; ndr_err = ndr_push_struct_blob( &blob, talloc_tos(), creds, (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(10, ("ndr_push_netlogon_creds_CredentialState failed: " "%s\n", ndr_errstr(ndr_err))); return false; } ret = secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, blob.data, blob.length); data_blob_free(&blob); return ret; }
/******************************************************************* Convert a secdesc into a byte stream ********************************************************************/ NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx, struct security_descriptor *secdesc, uint8 **data, size_t *len) { DATA_BLOB blob; enum ndr_err_code ndr_err; ndr_err = ndr_push_struct_blob( &blob, mem_ctx, secdesc, (ndr_push_flags_fn_t)ndr_push_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0, ("ndr_push_security_descriptor failed: %s\n", ndr_errstr(ndr_err))); return ndr_map_error2ntstatus(ndr_err);; } *data = blob.data; *len = blob.length; return NT_STATUS_OK; }
static NTSTATUS smbXsrv_open_global_parse_record(TALLOC_CTX *mem_ctx, struct db_record *rec, struct smbXsrv_open_global0 **global) { TDB_DATA key = dbwrap_record_get_key(rec); TDB_DATA val = dbwrap_record_get_value(rec); DATA_BLOB blob = data_blob_const(val.dptr, val.dsize); struct smbXsrv_open_globalB global_blob; enum ndr_err_code ndr_err; NTSTATUS status; TALLOC_CTX *frame = talloc_stackframe(); ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob, (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_open_globalB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:" "key '%s' ndr_pull_struct_blob - %s\n", hex_encode_talloc(frame, key.dptr, key.dsize), ndr_errstr(ndr_err))); status = ndr_map_error2ntstatus(ndr_err); goto done; } if (global_blob.version != SMBXSRV_VERSION_0) { status = NT_STATUS_INTERNAL_DB_CORRUPTION; DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:" "key '%s' unsuported version - %d - %s\n", hex_encode_talloc(frame, key.dptr, key.dsize), (int)global_blob.version, nt_errstr(status))); goto done; } *global = talloc_move(mem_ctx, &global_blob.info.info0); status = NT_STATUS_OK; done: talloc_free(frame); return status; }
NTSTATUS printing_tdb_migrate_secdesc(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct sec_desc_buf secdesc_ctr; DATA_BLOB blob; WERROR result; if (strequal(key_name, "printers")) { return NT_STATUS_OK; } blob = data_blob_const(data, length); ZERO_STRUCT(secdesc_ctr); ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr, (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("security descriptor pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name)); result = winreg_set_printer_secdesc(mem_ctx, b, key_name, secdesc_ctr.sd); if (!W_ERROR_IS_OK(result)) { return werror_to_ntstatus(result); } return NT_STATUS_OK; }
static NTSTATUS create_sys_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob, uint16_t hash_type, uint8_t hash[XATTR_SD_HASH_SIZE], const char *description, uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE]) { struct xattr_NTACL xacl; struct security_descriptor_hash_v4 sd_hs4; enum ndr_err_code ndr_err; TALLOC_CTX *ctx = talloc_tos(); NTTIME nttime_now; struct timeval now = timeval_current(); nttime_now = timeval_to_nttime(&now); ZERO_STRUCT(xacl); ZERO_STRUCT(sd_hs4); xacl.version = 4; xacl.info.sd_hs4 = &sd_hs4; xacl.info.sd_hs4->sd = discard_const_p(struct security_descriptor, psd); xacl.info.sd_hs4->hash_type = hash_type; memcpy(&xacl.info.sd_hs4->hash[0], hash, XATTR_SD_HASH_SIZE); xacl.info.sd_hs4->description = description; xacl.info.sd_hs4->time = nttime_now; memcpy(&xacl.info.sd_hs4->sys_acl_hash[0], sys_acl_hash, XATTR_SD_HASH_SIZE); ndr_err = ndr_push_struct_blob( pblob, ctx, &xacl, (ndr_push_flags_fn_t)ndr_push_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n", ndr_errstr(ndr_err))); return ndr_map_error2ntstatus(ndr_err); } return NT_STATUS_OK; }
static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, uint32 security_info, struct security_descriptor **ppdesc) { TALLOC_CTX *ctx = talloc_tos(); struct xattr_NTACL xacl; enum ndr_err_code ndr_err; size_t sd_size; ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl, (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n", ndr_errstr(ndr_err))); return ndr_map_error2ntstatus(ndr_err);; } if (xacl.version != 2) { return NT_STATUS_REVISION_MISMATCH; } *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs->sd->type | SEC_DESC_SELF_RELATIVE, (security_info & OWNER_SECURITY_INFORMATION) ? xacl.info.sd_hs->sd->owner_sid : NULL, (security_info & GROUP_SECURITY_INFORMATION) ? xacl.info.sd_hs->sd->group_sid : NULL, (security_info & SACL_SECURITY_INFORMATION) ? xacl.info.sd_hs->sd->sacl : NULL, (security_info & DACL_SECURITY_INFORMATION) ? xacl.info.sd_hs->sd->dacl : NULL, &sd_size); TALLOC_FREE(xacl.info.sd); return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; }
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; }
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; }
NTSTATUS leases_db_add(const struct GUID *client_guid, const struct smb2_lease_key *lease_key, const struct file_id *id, const char *servicepath, const char *base_name, const char *stream_name) { TDB_DATA db_key, db_value; DATA_BLOB blob; struct db_record *rec; NTSTATUS status; bool ok; struct leases_db_value new_value; struct leases_db_file new_file; struct leases_db_value *value = NULL; enum ndr_err_code ndr_err; if (!leases_db_init(false)) { return NT_STATUS_INTERNAL_ERROR; } ok = leases_db_key(talloc_tos(), client_guid, lease_key, &db_key); if (!ok) { DEBUG(10, ("%s: leases_db_key failed\n", __func__)); return NT_STATUS_NO_MEMORY; } rec = dbwrap_fetch_locked(leases_db, talloc_tos(), db_key); TALLOC_FREE(db_key.dptr); if (rec == NULL) { return NT_STATUS_INTERNAL_ERROR; } db_value = dbwrap_record_get_value(rec); if (db_value.dsize != 0) { uint32_t i; DEBUG(10, ("%s: record exists\n", __func__)); value = talloc(talloc_tos(), struct leases_db_value); if (value == NULL) { status = NT_STATUS_NO_MEMORY; goto out; } blob.data = db_value.dptr; blob.length = db_value.dsize; ndr_err = ndr_pull_struct_blob_all( &blob, value, value, (ndr_pull_flags_fn_t)ndr_pull_leases_db_value); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(10, ("%s: ndr_pull_struct_blob_failed: %s\n", __func__, ndr_errstr(ndr_err))); status = ndr_map_error2ntstatus(ndr_err); goto out; } /* id must be unique. */ for (i = 0; i < value->num_files; i++) { if (file_id_equal(id, &value->files[i].id)) { status = NT_STATUS_OBJECT_NAME_COLLISION; goto out; } } value->files = talloc_realloc(value, value->files, struct leases_db_file, value->num_files + 1); if (value->files == NULL) { status = NT_STATUS_NO_MEMORY; goto out; } value->files[value->num_files].id = *id; value->files[value->num_files].servicepath = servicepath; value->files[value->num_files].base_name = base_name; value->files[value->num_files].stream_name = stream_name; value->num_files += 1; } else {
NTSTATUS printing_tdb_migrate_driver(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length, bool do_string_conversion) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct ntprinting_driver r; struct spoolss_AddDriverInfoCtr d; struct spoolss_AddDriverInfo3 d3; struct spoolss_StringArray a; DATA_BLOB blob; WERROR result; const char *driver_name; uint32_t driver_version; blob = data_blob_const(data, length); ZERO_STRUCT(r); if (do_string_conversion) { r.string_flags = LIBNDR_FLAG_STR_ASCII; } ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("Driver pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } DEBUG(2, ("Migrating Printer Driver: %s\n", key_name)); ZERO_STRUCT(d3); ZERO_STRUCT(a); a.string = r.dependent_files; d3.architecture = r.environment; d3.config_file = r.configfile; d3.data_file = r.datafile; d3.default_datatype = r.defaultdatatype; d3.dependent_files = &a; d3.driver_path = r.driverpath; d3.help_file = r.helpfile; d3.monitor_name = r.monitorname; d3.driver_name = r.name; d3.version = r.version; d.level = 3; d.info.info3 = &d3; result = winreg_add_driver(mem_ctx, b, &d, &driver_name, &driver_version); if (!W_ERROR_IS_OK(result)) { return werror_to_ntstatus(result); } return NT_STATUS_OK; }
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 bool get_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32 *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)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE)); DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr)); if (dosattr & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); if (dosattr & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); if (dosattr & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); if (dosattr & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); if (dosattr & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); DEBUG(8,("\n")); 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 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 dos_mode_msdfs(connection_struct *conn, const struct smb_filename *smb_fname) { uint32 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; DEBUG(8,("dos_mode_msdfs returning ")); if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); return(result); }
NTSTATUS printing_tdb_migrate_printer(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length, bool do_string_conversion) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct ntprinting_printer r; struct spoolss_SetPrinterInfo2 info2; struct spoolss_DeviceMode dm; struct spoolss_DevmodeContainer devmode_ctr; DATA_BLOB blob; NTSTATUS status; WERROR result; int j; uint32_t info2_mask = (SPOOLSS_PRINTER_INFO_ALL) & ~SPOOLSS_PRINTER_INFO_SECDESC; if (strequal(key_name, "printers")) { return NT_STATUS_OK; } blob = data_blob_const(data, length); ZERO_STRUCT(r); if (do_string_conversion) { r.info.string_flags = LIBNDR_FLAG_STR_ASCII; } ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("printer pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } DEBUG(2, ("Migrating Printer: %s\n", key_name)); ZERO_STRUCT(devmode_ctr); /* Create printer info level 2 */ ZERO_STRUCT(info2); info2.attributes = r.info.attributes; info2.averageppm = r.info.averageppm; info2.cjobs = r.info.cjobs; info2.comment = r.info.comment; info2.datatype = r.info.datatype; info2.defaultpriority = r.info.default_priority; info2.drivername = r.info.drivername; info2.location = r.info.location; info2.parameters = r.info.parameters; info2.portname = r.info.portname; info2.printername = r.info.printername; info2.printprocessor = r.info.printprocessor; info2.priority = r.info.priority; info2.sepfile = r.info.sepfile; info2.sharename = r.info.sharename; info2.starttime = r.info.starttime; info2.status = r.info.status; info2.untiltime = r.info.untiltime; /* Create Device Mode */ if (r.devmode == NULL) { info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE; } else { ZERO_STRUCT(dm); dm.bitsperpel = r.devmode->bitsperpel; dm.collate = r.devmode->collate; dm.color = r.devmode->color; dm.copies = r.devmode->copies; dm.defaultsource = r.devmode->defaultsource; dm.devicename = r.devmode->devicename; dm.displayflags = r.devmode->displayflags; dm.displayfrequency = r.devmode->displayfrequency; dm.dithertype = r.devmode->dithertype; dm.driverversion = r.devmode->driverversion; dm.duplex = r.devmode->duplex; dm.fields = r.devmode->fields; dm.formname = r.devmode->formname; dm.icmintent = r.devmode->icmintent; dm.icmmethod = r.devmode->icmmethod; dm.logpixels = r.devmode->logpixels; dm.mediatype = r.devmode->mediatype; dm.orientation = r.devmode->orientation; dm.panningheight = r.devmode->pelsheight; dm.panningwidth = r.devmode->panningwidth; dm.paperlength = r.devmode->paperlength; dm.papersize = r.devmode->papersize; dm.paperwidth = r.devmode->paperwidth; dm.pelsheight = r.devmode->pelsheight; dm.pelswidth = r.devmode->pelswidth; dm.printquality = r.devmode->printquality; dm.size = r.devmode->size; dm.scale = r.devmode->scale; dm.specversion = r.devmode->specversion; dm.ttoption = r.devmode->ttoption; dm.yresolution = r.devmode->yresolution; if (r.devmode->nt_dev_private != NULL) { dm.driverextra_data.data = r.devmode->nt_dev_private->data; dm.driverextra_data.length = r.devmode->nt_dev_private->length; dm.__driverextra_length = r.devmode->nt_dev_private->length; } devmode_ctr.devmode = &dm; info2.devmode_ptr = 1; } result = winreg_update_printer(mem_ctx, b, key_name, info2_mask, &info2, &dm, NULL); if (!W_ERROR_IS_OK(result)) { DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n", key_name, win_errstr(result))); status = werror_to_ntstatus(result); goto done; } /* migrate printerdata */ for (j = 0; j < r.count; j++) { char *valuename; const char *keyname; if (r.printer_data[j].type == REG_NONE) { continue; } keyname = r.printer_data[j].name; valuename = strchr(keyname, '\\'); if (valuename == NULL) { continue; } else { valuename[0] = '\0'; valuename++; } result = winreg_set_printer_dataex(mem_ctx, b, key_name, keyname, valuename, r.printer_data[j].type, r.printer_data[j].data.data, r.printer_data[j].data.length); if (!W_ERROR_IS_OK(result)) { DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], " "valuename [%s] refused -- %s.\n", key_name, keyname, valuename, win_errstr(result))); status = werror_to_ntstatus(result); break; } } status = NT_STATUS_OK; done: return status; }
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) { DBG_INFO("Cannot get attribute " "from EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno)); 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; }
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); }