NTSTATUS cli_query_security_descriptor(struct cli_state *cli, uint16_t fnum, uint32_t sec_info, TALLOC_CTX *mem_ctx, struct security_descriptor **sd) { uint8_t param[8]; uint8_t *rdata=NULL; uint32_t rdata_count=0; NTSTATUS status; struct security_descriptor *lsd; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { return cli_smb2_query_security_descriptor(cli, fnum, sec_info, mem_ctx, sd); } SIVAL(param, 0, fnum); SIVAL(param, 4, sec_info); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_QUERY_SECURITY_DESC, 0, /* function, flags */ NULL, 0, 0, /* setup, length, max */ param, 8, 4, /* param, length, max */ NULL, 0, 0x10000, /* data, length, max */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup, length */ NULL, 0, NULL, &rdata, 0, &rdata_count); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("NT_TRANSACT_QUERY_SECURITY_DESC failed: %s\n", nt_errstr(status))); goto cleanup; } status = unmarshall_sec_desc(mem_ctx, (uint8 *)rdata, rdata_count, &lsd); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("unmarshall_sec_desc failed: %s\n", nt_errstr(status))); goto cleanup; } if (sd != NULL) { *sd = lsd; } else { TALLOC_FREE(lsd); } cleanup: TALLOC_FREE(rdata); return status; }
/**************************************************************************** check for existance of a trans2 call ****************************************************************************/ static NTSTATUS try_trans2(struct cli_state *cli, int op, uint8_t *param, uint8_t *data, uint32_t param_len, uint32_t data_len, uint32_t *rparam_len, uint32_t *rdata_len) { uint16_t setup[1]; uint8_t *rparam=NULL, *rdata=NULL; NTSTATUS status; SSVAL(setup+0, 0, op); status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, /* name, fid */ op, 0, NULL, 0, 0, /* setup */ param, param_len, 2, data, data_len, CLI_BUFFER_SIZE, NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ &rparam, 0, rparam_len, &rdata, 0, rdata_len); TALLOC_FREE(rdata); TALLOC_FREE(rparam); return status; }
/**************************************************************************** check for existance of a nttrans call ****************************************************************************/ static NTSTATUS try_nttrans(struct cli_state *cli, int op, uint8_t *param, uint8_t *data, int32_t param_len, uint32_t data_len, uint32_t *rparam_len, uint32_t *rdata_len) { uint8_t *rparam=NULL, *rdata=NULL; NTSTATUS status; status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ op, 0, NULL, 0, 0, /* setup */ param, param_len, 2, data, data_len, CLI_BUFFER_SIZE, NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ &rparam, 0, rparam_len, &rdata, 0, rdata_len); SAFE_FREE(rdata); SAFE_FREE(rparam); return status; }
NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt) { uint16_t setup[1]; uint8_t params[16]; unsigned int data_len; uint8_t data[SID_MAX_SIZE+8]; uint8_t *rparam, *rdata; uint32_t rparam_count, rdata_count; unsigned int sid_len; unsigned int offset; NTSTATUS status; if (!cli||!pqt) { smb_panic("cli_get_user_quota() called with NULL Pointer!"); } SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA); SSVAL(params, 0,quota_fnum); SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_FOR_SID); SIVAL(params, 4,0x00000024); SIVAL(params, 8,0x00000000); SIVAL(params,12,0x00000024); sid_len = ndr_size_dom_sid(&pqt->sid, 0); data_len = sid_len+8; SIVAL(data, 0, 0x00000000); SIVAL(data, 4, sid_len); sid_linearize((char *)data+8, sid_len, &pqt->sid); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_GET_USER_QUOTA, 0, setup, 1, 0, /* setup */ params, 16, 4, /* params */ data, data_len, 112, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ &rparam, 4, &rparam_count, &rdata, 8, &rdata_count); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n", nt_errstr(status))); return status; } if (!parse_user_quota_record(rdata, rdata_count, &offset, pqt)) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n")); } TALLOC_FREE(rparam); TALLOC_FREE(rdata); return status; }
bool cli_api(struct cli_state *cli, char *param, int prcnt, int mprcnt, char *data, int drcnt, int mdrcnt, char **rparam, unsigned int *rprcnt, char **rdata, unsigned int *rdrcnt) { NTSTATUS status; uint8_t *my_rparam, *my_rdata; uint32_t num_my_rparam, num_my_rdata; status = cli_trans(talloc_tos(), cli, SMBtrans, PIPE_LANMAN, 0, /* name, fid */ 0, 0, /* function, flags */ NULL, 0, 0, /* setup */ (uint8_t *)param, prcnt, mprcnt, /* Params, length, max */ (uint8_t *)data, drcnt, mdrcnt, /* Data, length, max */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ &my_rparam, 0, &num_my_rparam, &my_rdata, 0, &num_my_rdata); if (!NT_STATUS_IS_OK(status)) { return false; } /* * I know this memcpy massively hurts, but there are just tons * of callers of cli_api that eventually need changing to * talloc */ *rparam = (char *)smb_memdup(my_rparam, num_my_rparam); if (*rparam == NULL) { goto fail; } *rprcnt = num_my_rparam; TALLOC_FREE(my_rparam); *rdata = (char *)smb_memdup(my_rdata, num_my_rdata); if (*rdata == NULL) { goto fail; } *rdrcnt = num_my_rdata; TALLOC_FREE(my_rdata); return true; fail: TALLOC_FREE(my_rdata); TALLOC_FREE(my_rparam); *rparam = NULL; *rprcnt = 0; *rdata = NULL; *rdrcnt = 0; return false; }
NTSTATUS cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt) { uint16_t setup[1]; uint8_t param[2]; uint8_t *rdata=NULL; uint32_t rdata_count=0; SMB_NTQUOTA_STRUCT qt; NTSTATUS status; ZERO_STRUCT(qt); if (!cli||!pqt) { smb_panic("cli_get_fs_quota_info() called with NULL Pointer!"); } SSVAL(setup + 0, 0, TRANSACT2_QFSINFO); SSVAL(param,0,SMB_FS_QUOTA_INFORMATION); status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, /* name, fid */ 0, 0, /* function, flags */ setup, 1, 0, /* setup */ param, 2, 0, /* param */ NULL, 0, 560, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, /* rparam */ &rdata, 48, &rdata_count); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n", nt_errstr(status))); return status; } /* unknown_1 24 NULL bytes in pdata*/ /* the soft quotas 8 bytes (uint64_t)*/ qt.softlim = BVAL(rdata,24); /* the hard quotas 8 bytes (uint64_t)*/ qt.hardlim = BVAL(rdata,32); /* quota_flags 2 bytes **/ qt.qflags = SVAL(rdata,40); qt.qtype = SMB_USER_FS_QUOTA_TYPE; *pqt = qt; TALLOC_FREE(rdata); return status; }
NTSTATUS cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt) { uint16_t setup[1]; uint8_t param[4]; uint8_t data[48]; SMB_NTQUOTA_STRUCT qt; NTSTATUS status; ZERO_STRUCT(qt); memset(data,'\0',48); if (!cli||!pqt) { smb_panic("cli_set_fs_quota_info() called with NULL Pointer!"); } SSVAL(setup + 0, 0,TRANSACT2_SETFSINFO); SSVAL(param,0,quota_fnum); SSVAL(param,2,SMB_FS_QUOTA_INFORMATION); /* Unknown1 24 NULL bytes*/ /* Default Soft Quota 8 bytes */ SBIG_UINT(data,24,pqt->softlim); /* Default Hard Quota 8 bytes */ SBIG_UINT(data,32,pqt->hardlim); /* Quota flag 2 bytes */ SSVAL(data,40,pqt->qflags); /* Unknown3 6 NULL bytes */ status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, /* name, fid */ 0, 0, /* function, flags */ setup, 1, 0, /* setup */ param, 8, 0, /* param */ data, 48, 0, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, /* rparam */ NULL, 0, NULL); /* rdata */ if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n", nt_errstr(status))); } return status; }
NTSTATUS cli_set_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt) { uint16_t setup[1]; uint8_t params[2]; uint8_t data[112]; unsigned int sid_len; NTSTATUS status; memset(data,'\0',112); if (!cli||!pqt) { smb_panic("cli_set_user_quota() called with NULL Pointer!"); } SSVAL(setup + 0, 0, NT_TRANSACT_SET_USER_QUOTA); SSVAL(params,0,quota_fnum); sid_len = ndr_size_dom_sid(&pqt->sid, 0); SIVAL(data,0,0); SIVAL(data,4,sid_len); SBIG_UINT(data, 8,(uint64_t)0); SBIG_UINT(data,16,pqt->usedspace); SBIG_UINT(data,24,pqt->softlim); SBIG_UINT(data,32,pqt->hardlim); sid_linearize((char *)data+40, sid_len, &pqt->sid); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_SET_USER_QUOTA, 0, setup, 1, 0, /* setup */ params, 2, 0, /* params */ data, 112, 0, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, /* rparams */ NULL, 0, NULL); /* rdata */ if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n", nt_errstr(status))); } return status; }
/**************************************************************************** query the security descriptor for a open file ****************************************************************************/ struct security_descriptor *cli_query_secdesc(struct cli_state *cli, uint16_t fnum, TALLOC_CTX *mem_ctx) { uint8_t param[8]; uint8_t *rdata=NULL; uint32_t rdata_count=0; struct security_descriptor *psd = NULL; NTSTATUS status; SIVAL(param, 0, fnum); SIVAL(param, 4, 0x7); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_QUERY_SECURITY_DESC, 0, /* function, flags */ NULL, 0, 0, /* setup, length, max */ param, 8, 4, /* param, length, max */ NULL, 0, 0x10000, /* data, length, max */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup, length */ NULL, 0, NULL, &rdata, 0, &rdata_count); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("NT_TRANSACT_QUERY_SECURITY_DESC failed: %s\n", nt_errstr(status))); goto cleanup; } status = unmarshall_sec_desc(mem_ctx, (uint8 *)rdata, rdata_count, &psd); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("unmarshall_sec_desc failed: %s\n", nt_errstr(status))); goto cleanup; } cleanup: TALLOC_FREE(rdata); return psd; }
/**************************************************************************** set the security descriptor for a open file ****************************************************************************/ NTSTATUS cli_set_security_descriptor(struct cli_state *cli, uint16_t fnum, uint32_t sec_info, const struct security_descriptor *sd) { uint8_t param[8]; uint8 *data; size_t len; NTSTATUS status; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { return cli_smb2_set_security_descriptor(cli, fnum, sec_info, sd); } status = marshall_sec_desc(talloc_tos(), sd, &data, &len); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("marshall_sec_desc failed: %s\n", nt_errstr(status))); return status; } SIVAL(param, 0, fnum); SIVAL(param, 4, sec_info); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_SET_SECURITY_DESC, 0, NULL, 0, 0, /* setup */ param, 8, 0, /* param */ data, len, 0, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, /* rparam */ NULL, 0, NULL); /* rdata */ TALLOC_FREE(data); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to send NT_TRANSACT_SET_SECURITY_DESC: %s\n", nt_errstr(status))); } return status; }
/**************************************************************************** set the security descriptor for a open file ****************************************************************************/ NTSTATUS cli_set_secdesc(struct cli_state *cli, uint16_t fnum, struct security_descriptor *sd) { uint8_t param[8]; uint32 sec_info = 0; uint8 *data; size_t len; NTSTATUS status; status = marshall_sec_desc(talloc_tos(), sd, &data, &len); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("marshall_sec_desc failed: %s\n", nt_errstr(status))); return status; } SIVAL(param, 0, fnum); if (sd->dacl) sec_info |= SECINFO_DACL; if (sd->owner_sid) sec_info |= SECINFO_OWNER; if (sd->group_sid) sec_info |= SECINFO_GROUP; SSVAL(param, 4, sec_info); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_SET_SECURITY_DESC, 0, NULL, 0, 0, /* setup */ param, 8, 0, /* param */ data, len, 0, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, /* rparam */ NULL, 0, NULL); /* rdata */ TALLOC_FREE(data); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to send NT_TRANSACT_SET_SECURITY_DESC: %s\n", nt_errstr(status))); } return status; }
NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx, struct cli_state *cli, const char *path, struct client_dfs_referral **refs, size_t *num_refs, size_t *consumed) { unsigned int data_len = 0; unsigned int param_len = 0; uint16_t setup[1]; uint16_t recv_flags2; uint8_t *param = NULL; uint8_t *rdata = NULL; char *p; char *endp; smb_ucs2_t *path_ucs; char *consumed_path = NULL; uint16_t consumed_ucs; uint16 num_referrals; struct client_dfs_referral *referrals = NULL; NTSTATUS status; TALLOC_CTX *frame = talloc_stackframe(); *num_refs = 0; *refs = NULL; SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL); param = talloc_array(talloc_tos(), uint8_t, 2); if (!param) { status = NT_STATUS_NO_MEMORY; goto out; } SSVAL(param, 0, 0x03); /* max referral level */ param = trans2_bytes_push_str(param, cli_ucs2(cli), path, strlen(path)+1, NULL); if (!param) { status = NT_STATUS_NO_MEMORY; goto out; } param_len = talloc_get_size(param); path_ucs = (smb_ucs2_t *)¶m[2]; status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0xffff, 0, 0, setup, 1, 0, param, param_len, 2, NULL, 0, CLI_BUFFER_SIZE, &recv_flags2, NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, &rdata, 4, &data_len); if (!NT_STATUS_IS_OK(status)) { goto out; } endp = (char *)rdata + data_len; consumed_ucs = SVAL(rdata, 0); num_referrals = SVAL(rdata, 2); /* consumed_ucs is the number of bytes * of the UCS2 path consumed not counting any * terminating null. We need to convert * back to unix charset and count again * to get the number of bytes consumed from * the incoming path. */ errno = 0; if (pull_string_talloc(talloc_tos(), NULL, 0, &consumed_path, path_ucs, consumed_ucs, STR_UNICODE) == 0) { if (errno != 0) { status = map_nt_error_from_unix(errno); } else { status = NT_STATUS_INVALID_NETWORK_RESPONSE; } goto out; } if (consumed_path == NULL) { status = map_nt_error_from_unix(errno); goto out; } *consumed = strlen(consumed_path); if (num_referrals != 0) { uint16 ref_version; uint16 ref_size; int i; uint16 node_offset; referrals = talloc_array(ctx, struct client_dfs_referral, num_referrals); if (!referrals) { status = NT_STATUS_NO_MEMORY; goto out; } /* start at the referrals array */ p = (char *)rdata+8; for (i=0; i<num_referrals && p < endp; i++) { if (p + 18 > endp) { goto out; } ref_version = SVAL(p, 0); ref_size = SVAL(p, 2); node_offset = SVAL(p, 16); if (ref_version != 3) { p += ref_size; continue; } referrals[i].proximity = SVAL(p, 8); referrals[i].ttl = SVAL(p, 10); if (p + node_offset > endp) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } clistr_pull_talloc(referrals, (const char *)rdata, recv_flags2, &referrals[i].dfspath, p+node_offset, PTR_DIFF(endp, p+node_offset), STR_TERMINATE|STR_UNICODE); if (!referrals[i].dfspath) { status = map_nt_error_from_unix(errno); goto out; } p += ref_size; } if (i < num_referrals) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } }
NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx, struct cli_state *cli, const char *path, struct client_dfs_referral **refs, size_t *num_refs, size_t *consumed) { unsigned int param_len = 0; uint16_t recv_flags2; uint8_t *param = NULL; uint8_t *rdata = NULL; char *p; char *endp; smb_ucs2_t *path_ucs; char *consumed_path = NULL; uint16_t consumed_ucs; uint16_t num_referrals; struct client_dfs_referral *referrals = NULL; NTSTATUS status; TALLOC_CTX *frame = talloc_stackframe(); *num_refs = 0; *refs = NULL; param = talloc_array(talloc_tos(), uint8_t, 2); if (!param) { status = NT_STATUS_NO_MEMORY; goto out; } SSVAL(param, 0, 0x03); /* max referral level */ param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn), path, strlen(path)+1, NULL); if (!param) { status = NT_STATUS_NO_MEMORY; goto out; } param_len = talloc_get_size(param); path_ucs = (smb_ucs2_t *)¶m[2]; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { DATA_BLOB in_input_buffer; DATA_BLOB in_output_buffer = data_blob_null; DATA_BLOB out_input_buffer = data_blob_null; DATA_BLOB out_output_buffer = data_blob_null; in_input_buffer.data = param; in_input_buffer.length = param_len; status = smb2cli_ioctl(cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon, UINT64_MAX, /* in_fid_persistent */ UINT64_MAX, /* in_fid_volatile */ FSCTL_DFS_GET_REFERRALS, 0, /* in_max_input_length */ &in_input_buffer, CLI_BUFFER_SIZE, /* in_max_output_length */ &in_output_buffer, SMB2_IOCTL_FLAG_IS_FSCTL, talloc_tos(), &out_input_buffer, &out_output_buffer); if (!NT_STATUS_IS_OK(status)) { goto out; } if (out_output_buffer.length < 4) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } recv_flags2 = FLAGS2_UNICODE_STRINGS; rdata = out_output_buffer.data; endp = (char *)rdata + out_output_buffer.length; } else { unsigned int data_len = 0; uint16_t setup[1]; SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL); status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0xffff, 0, 0, setup, 1, 0, param, param_len, 2, NULL, 0, CLI_BUFFER_SIZE, &recv_flags2, NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, &rdata, 4, &data_len); if (!NT_STATUS_IS_OK(status)) { goto out; } endp = (char *)rdata + data_len; } consumed_ucs = SVAL(rdata, 0); num_referrals = SVAL(rdata, 2); /* consumed_ucs is the number of bytes * of the UCS2 path consumed not counting any * terminating null. We need to convert * back to unix charset and count again * to get the number of bytes consumed from * the incoming path. */ errno = 0; if (pull_string_talloc(talloc_tos(), NULL, 0, &consumed_path, path_ucs, consumed_ucs, STR_UNICODE) == 0) { if (errno != 0) { status = map_nt_error_from_unix(errno); } else { status = NT_STATUS_INVALID_NETWORK_RESPONSE; } goto out; } if (consumed_path == NULL) { status = map_nt_error_from_unix(errno); goto out; } *consumed = strlen(consumed_path); if (num_referrals != 0) { uint16_t ref_version; uint16_t ref_size; int i; uint16_t node_offset; referrals = talloc_array(ctx, struct client_dfs_referral, num_referrals); if (!referrals) { status = NT_STATUS_NO_MEMORY; goto out; } /* start at the referrals array */ p = (char *)rdata+8; for (i=0; i<num_referrals && p < endp; i++) { if (p + 18 > endp) { goto out; } ref_version = SVAL(p, 0); ref_size = SVAL(p, 2); node_offset = SVAL(p, 16); if (ref_version != 3) { p += ref_size; continue; } referrals[i].proximity = SVAL(p, 8); referrals[i].ttl = SVAL(p, 10); if (p + node_offset > endp) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } clistr_pull_talloc(referrals, (const char *)rdata, recv_flags2, &referrals[i].dfspath, p+node_offset, PTR_DIFF(endp, p+node_offset), STR_TERMINATE|STR_UNICODE); if (!referrals[i].dfspath) { status = map_nt_error_from_unix(errno); goto out; } p += ref_size; } if (i < num_referrals) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } }
NTSTATUS cli_list_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST **pqt_list) { uint16_t setup[1]; uint8_t params[16]; uint8_t *rparam=NULL, *rdata=NULL; uint32_t rparam_count=0, rdata_count=0; unsigned int offset; const uint8_t *curdata = NULL; unsigned int curdata_count = 0; TALLOC_CTX *mem_ctx = NULL; SMB_NTQUOTA_STRUCT qt; SMB_NTQUOTA_LIST *tmp_list_ent; NTSTATUS status; if (!cli||!pqt_list) { smb_panic("cli_list_user_quota() called with NULL Pointer!"); } SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA); SSVAL(params, 0,quota_fnum); SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START); SIVAL(params, 4,0x00000000); SIVAL(params, 8,0x00000000); SIVAL(params,12,0x00000000); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_GET_USER_QUOTA, 0, setup, 1, 0, /* setup */ params, 16, 4, /* params */ NULL, 0, 2048, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ &rparam, 0, &rparam_count, &rdata, 0, &rdata_count); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n", nt_errstr(status))); goto cleanup; } if (rdata_count == 0) { *pqt_list = NULL; return NT_STATUS_OK; } if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) { DEBUG(0,("talloc_init() failed\n")); return NT_STATUS_NO_MEMORY; } offset = 1; for (curdata=rdata,curdata_count=rdata_count; ((curdata)&&(curdata_count>=8)&&(offset>0)); curdata +=offset,curdata_count -= offset) { ZERO_STRUCT(qt); if (!parse_user_quota_record((const uint8_t *)curdata, curdata_count, &offset, &qt)) { DEBUG(1,("Failed to parse the quota record\n")); goto cleanup; } if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } memcpy(tmp_list_ent->quotas,&qt,sizeof(qt)); tmp_list_ent->mem_ctx = mem_ctx; DLIST_ADD((*pqt_list),tmp_list_ent); } SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE); while(1) { TALLOC_FREE(rparam); TALLOC_FREE(rdata); status = cli_trans(talloc_tos(), cli, SMBnttrans, NULL, -1, /* name, fid */ NT_TRANSACT_GET_USER_QUOTA, 0, setup, 1, 0, /* setup */ params, 16, 4, /* params */ NULL, 0, 2048, /* data */ NULL, /* recv_flags2 */ NULL, 0, NULL, /* rsetup */ &rparam, 0, &rparam_count, &rdata, 0, &rdata_count); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n", nt_errstr(status))); goto cleanup; } if (rdata_count == 0) { break; } offset = 1; for (curdata=rdata,curdata_count=rdata_count; ((curdata)&&(curdata_count>=8)&&(offset>0)); curdata +=offset,curdata_count -= offset) { ZERO_STRUCT(qt); if (!parse_user_quota_record((const uint8_t *)curdata, curdata_count, &offset, &qt)) { DEBUG(1,("Failed to parse the quota record\n")); goto cleanup; } if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); talloc_destroy(mem_ctx); goto cleanup; } if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) { DEBUG(0,("TALLOC_ZERO() failed\n")); talloc_destroy(mem_ctx); goto cleanup; } memcpy(tmp_list_ent->quotas,&qt,sizeof(qt)); tmp_list_ent->mem_ctx = mem_ctx; DLIST_ADD((*pqt_list),tmp_list_ent); } } cleanup: TALLOC_FREE(rparam); TALLOC_FREE(rdata); return status; }