From 099974aa1575bf580c69c3848bc73d5d3b4b2bf3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 29 Mar 2004 22:21:47 +0000 Subject: Fix get/set of EA's in client library. Added torture test for it. Jeremy. (This used to be commit 0d239a9c070bdc1ce2d2806fc02549c4750597aa) --- source3/libsmb/clifile.c | 237 +++++++++++++++++++++++++++++++--------------- source3/torture/torture.c | 21 +++- 2 files changed, 180 insertions(+), 78 deletions(-) diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 23c98c16f3..52164dc0b4 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -1163,28 +1163,18 @@ NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB * } /********************************************************* - Set an extended attribute on a pathname. + Set an extended attribute utility fn. *********************************************************/ -BOOL cli_set_path_ea(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len) -{ +static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len, + const char *ea_name, const char *ea_val, size_t ea_len) +{ unsigned int data_len = 0; - unsigned int param_len = 0; - uint16 setup = TRANSACT2_SETPATHINFO; - char param[sizeof(pstring)+6]; char *data = NULL; char *rparam=NULL, *rdata=NULL; char *p; - size_t srclen = 2*(strlen(path)+1); size_t ea_namelen = strlen(ea_name); - memset(param, 0, sizeof(param)); - SSVAL(param,0,SMB_INFO_SET_EA); - p = ¶m[6]; - - p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE); - param_len = PTR_DIFF(p, param); - data_len = 4 + 4 + ea_namelen + 1 + ea_len; data = malloc(data_len); if (!data) { @@ -1223,82 +1213,65 @@ BOOL cli_set_path_ea(struct cli_state *cli, const char *path, const char *ea_nam } /********************************************************* - Set an extended attribute on an fnum. + Set an extended attribute on a pathname. *********************************************************/ -BOOL cli_set_fnum_ea(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len) +BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len) { - unsigned int data_len = 0; - unsigned int param_len = 6; - uint16 setup = TRANSACT2_SETFILEINFO; - pstring param; - char *data = NULL; - char *rparam=NULL, *rdata=NULL; + uint16 setup = TRANSACT2_SETPATHINFO; + unsigned int param_len = 0; + char param[sizeof(pstring)+6]; + size_t srclen = 2*(strlen(path)+1); char *p; - size_t ea_namelen = strlen(ea_name); memset(param, 0, sizeof(param)); - SSVAL(param,0,fnum); - SSVAL(param,2,SMB_INFO_SET_EA); + SSVAL(param,0,SMB_INFO_SET_EA); + p = ¶m[6]; - data_len = 4 + 4 + ea_namelen + 1 + ea_len; - data = malloc(data_len); - if (!data) { - return False; - } - p = data; - SIVAL(p,0,data_len); - p += 4; - SCVAL(p, 0, 0); /* EA flags. */ - SCVAL(p, 1, ea_namelen); - SSVAL(p, 2, ea_len); - memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */ - memcpy(p+4+ea_namelen+1, ea_val, ea_len); + p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE); + param_len = PTR_DIFF(p, param); - if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - data, data_len, cli->max_xmit /* data, length, max */ - )) { - return False; - } + return cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len); +} - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, ¶m_len, - &rdata, &data_len)) { - return False; - } +/********************************************************* + Set an extended attribute on an fnum. +*********************************************************/ - SAFE_FREE(data); - SAFE_FREE(rdata); - SAFE_FREE(rparam); +BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len) +{ + char param[6]; + uint16 setup = TRANSACT2_SETFILEINFO; - return True; + memset(param, 0, 6); + SSVAL(param,0,fnum); + SSVAL(param,2,SMB_INFO_SET_EA); + + return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len); } -BOOL cli_get_eas(struct cli_state *cli, const char *path, +/********************************************************* + Get an extended attribute list tility fn. +*********************************************************/ + +static BOOL cli_get_ea_list(struct cli_state *cli, + uint16 setup, char *param, unsigned int param_len, TALLOC_CTX *ctx, size_t *pnum_eas, - struct ea_struct **ea_list) + struct ea_struct **pea_list) { unsigned int data_len = 0; - unsigned int param_len = 0; unsigned int rparam_len, rdata_len; - uint16 setup = TRANSACT2_QPATHINFO; - pstring param; char *rparam=NULL, *rdata=NULL; char *p; - - p = param; - memset(p, 0, 6); - SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS); - p += 6; - p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE); - - param_len = PTR_DIFF(p, param); - + size_t ea_size; + size_t num_eas; + BOOL ret = False; + struct ea_struct *ea_list; + + *pnum_eas = 0; + *pea_list = NULL; + if (!cli_send_trans(cli, SMBtrans2, NULL, /* Name */ -1, 0, /* fid, flags */ @@ -1308,15 +1281,131 @@ BOOL cli_get_eas(struct cli_state *cli, const char *path, )) { return False; } - + if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_len, &rdata, &rdata_len)) { return False; } - + if (!rdata || rdata_len < 4) { - return False; + goto out; } - return False; + + ea_size = (size_t)IVAL(rdata,0); + if (ea_size > rdata_len) { + goto out; + } + + p = rdata + 4; + ea_size -= 4; + + /* Validate the EA list and count it. */ + for (num_eas = 0; ea_size >= 4; num_eas++) { + unsigned int ea_namelen = CVAL(p,1); + unsigned int ea_valuelen = SVAL(p,2); + if (ea_namelen == 0) { + goto out; + } + if (4 + ea_namelen + 1 + ea_valuelen > ea_size) { + goto out; + } + ea_size -= 4 + ea_namelen + 1 + ea_valuelen; + p += 4 + ea_namelen + 1 + ea_valuelen; + } + + if (num_eas == 0) { + ret = True; + goto out; + } + + *pnum_eas = num_eas; + if (!pea_list) { + /* Caller only wants number of EA's. */ + ret = True; + goto out; + } + + ea_list = (struct ea_struct *)talloc(ctx, num_eas*sizeof(struct ea_struct)); + if (!ea_list) { + goto out; + } + + ea_size = (size_t)IVAL(rdata,0); + p = rdata + 4; + + for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) { + struct ea_struct *ea = &ea_list[num_eas]; + fstring unix_ea_name; + unsigned int ea_namelen = CVAL(p,1); + unsigned int ea_valuelen = SVAL(p,2); + + ea->flags = CVAL(p,0); + unix_ea_name[0] = '\0'; + pull_ascii_fstring(unix_ea_name, p + 4); + ea->name = talloc_strdup(ctx, unix_ea_name); + /* Ensure the value is null terminated (in case it's a string). */ + ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1); + if (!ea->value.data) { + goto out; + } + if (ea_valuelen) { + memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen); + } + ea->value.data[ea_valuelen] = 0; + ea->value.length--; + p += 4 + ea_namelen + 1 + ea_valuelen; + } + + *pea_list = ea_list; + ret = True; + + out : + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return ret; +} + +/********************************************************* + Get an extended attribute list from a pathname. +*********************************************************/ + +BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path, + TALLOC_CTX *ctx, + size_t *pnum_eas, + struct ea_struct **pea_list) +{ + uint16 setup = TRANSACT2_QPATHINFO; + unsigned int param_len = 0; + char param[sizeof(pstring)+6]; + char *p; + + p = param; + memset(p, 0, 6); + SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS); + p += 6; + p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE); + param_len = PTR_DIFF(p, param); + + return cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list); +} + +/********************************************************* + Get an extended attribute list from an fnum. +*********************************************************/ + +BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum, + TALLOC_CTX *ctx, + size_t *pnum_eas, + struct ea_struct **pea_list) +{ + uint16 setup = TRANSACT2_QFILEINFO; + char param[6]; + + memset(param, 0, 6); + SSVAL(param,0,fnum); + SSVAL(param,2,SMB_INFO_SET_EA); + + return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list); } diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 3a250c1e14..97bca82d9b 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -4316,6 +4316,9 @@ static BOOL run_eatest(int dummy) const char *fname = "\\eatest.txt"; BOOL correct = True; int fnum, i; + size_t num_eas; + struct ea_struct *ea_list = NULL; + TALLOC_CTX *mem_ctx = talloc_init("eatest"); printf("starting eatest\n"); @@ -4339,7 +4342,7 @@ static BOOL run_eatest(int dummy) slprintf(ea_name, sizeof(ea_name), "EA_%d", i); memset(ea_val, (char)i+1, i+1); - if (!cli_set_fnum_ea(cli, fnum, ea_name, ea_val, i+1)) { + if (!cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1)) { printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli)); return False; } @@ -4349,17 +4352,27 @@ static BOOL run_eatest(int dummy) for (i = 0; i < 10; i++) { fstring ea_name, ea_val; - slprintf(ea_name, sizeof(ea_name), "EA_%d", i); + slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10); memset(ea_val, (char)i+1, i+1); - if (!cli_set_path_ea(cli, fname, ea_name, ea_val, i+1)) { + if (!cli_set_ea_path(cli, fname, ea_name, ea_val, i+1)) { printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli)); return False; } } - cli_get_eas(cli, fname, NULL,NULL,NULL); + if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) { + printf("ea_get list failed - %s\n", cli_errstr(cli)); + correct = False; + } + + printf("num_eas = %d\n", num_eas); + for (i = 0; i < num_eas; i++) { + printf("%d: ea_name = %s. Val = ", i, ea_list[i].name); + dump_data(0, ea_list[i].value.data, ea_list[i].value.length); + } + talloc_destroy(mem_ctx); if (!torture_close_connection(cli)) { correct = False; } -- cgit