static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user, const char *pass, const char *workgroup) { uint32 capabilities = cli_session_setup_capabilities(cli); fstring pword; int passlen; char *p; passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE|STR_CONVERT); set_message(cli->outbuf,13,0,True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); cli_setup_packet(cli); SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); SSVAL(cli->outbuf,smb_vwv3,2); SSVAL(cli->outbuf,smb_vwv4,cli->pid); SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); SSVAL(cli->outbuf,smb_vwv8,0); SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); memcpy(p, pword, passlen); p += passlen; p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_CONVERT); /* username */ p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_CONVERT); /* workgroup */ p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE|STR_CONVERT); p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE|STR_CONVERT); cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; show_msg(cli->inbuf); if (cli_is_error(cli)) { return False; } cli->vuid = SVAL(cli->inbuf,smb_uid); p = smb_buf(cli->inbuf); p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); fstrcpy(cli->user_name, user); return True; }
bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate) { bool ret = False; uint16 setup; char param[2]; char *rparam=NULL, *rdata=NULL; unsigned int rparam_count=0, rdata_count=0; unsigned int nlen; setup = TRANSACT2_QFSINFO; SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO); if (!cli_send_trans(cli, SMBtrans2, NULL, 0, 0, &setup, 1, 0, param, 2, 0, NULL, 0, 560)) { goto cleanup; } if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_count, &rdata, &rdata_count)) { goto cleanup; } if (cli_is_error(cli)) { ret = False; goto cleanup; } else { ret = True; } if (rdata_count < 19) { goto cleanup; } if (pdate) { struct timespec ts; ts = interpret_long_date(rdata); *pdate = ts.tv_sec; } if (pserial_number) { *pserial_number = IVAL(rdata,8); } nlen = IVAL(rdata,12); clistr_pull(cli, volume_name, rdata + 18, sizeof(fstring), nlen, STR_UNICODE); /* todo: but not yet needed * return the other stuff */ cleanup: SAFE_FREE(rparam); SAFE_FREE(rdata); return ret; }
NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name) { unsigned int data_len = 0; unsigned int param_len = 0; uint16 setup = TRANSACT2_QPATHINFO; pstring param; char *rparam=NULL, *rdata=NULL; int count=8; char *p; BOOL ret; unsigned int len; p = param; memset(p, 0, 6); SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO); p += 6; p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE); param_len = PTR_DIFF(p, param); do { ret = (cli_send_trans(cli, SMBtrans2, NULL, /* Name */ -1, 0, /* fid, flags */ &setup, 1, 0, /* setup, length, max */ param, param_len, 10, /* param, length, max */ NULL, data_len, cli->max_xmit /* data, length, max */ ) && cli_receive_trans(cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len)); if (!ret && cli_is_dos_error(cli)) { /* we need to work around a Win95 bug - sometimes it gives ERRSRV/ERRerror temprarily */ uint8 eclass; uint32 ecode; cli_dos_error(cli, &eclass, &ecode); if (eclass != ERRSRV || ecode != ERRerror) break; smb_msleep(100); } } while (count-- && ret==False); if (!ret || !rdata || data_len < 4) { return NT_STATUS_UNSUCCESSFUL; } len = IVAL(rdata, 0); if (len > data_len - 4) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE); SAFE_FREE(rdata); SAFE_FREE(rparam); return NT_STATUS_OK; }
bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number) { bool ret = False; uint16 setup; char param[2]; char *rparam=NULL, *rdata=NULL; unsigned int rparam_count=0, rdata_count=0; unsigned char nlen; setup = TRANSACT2_QFSINFO; SSVAL(param,0,SMB_INFO_VOLUME); if (!cli_send_trans(cli, SMBtrans2, NULL, 0, 0, &setup, 1, 0, param, 2, 0, NULL, 0, 560)) { goto cleanup; } if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_count, &rdata, &rdata_count)) { goto cleanup; } if (cli_is_error(cli)) { ret = False; goto cleanup; } else { ret = True; } if (rdata_count < 5) { goto cleanup; } if (pserial_number) { *pserial_number = IVAL(rdata,0); } nlen = CVAL(rdata,l2_vol_cch); clistr_pull(cli, volume_name, rdata + l2_vol_szVolLabel, sizeof(fstring), nlen, STR_NOALIGN); /* todo: but not yet needed * return the other stuff */ cleanup: SAFE_FREE(rparam); SAFE_FREE(rdata); return ret; }
int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path) { int len; char *p; memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,3,0,True); SCVAL(cli->outbuf,smb_com,SMBctemp); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); SSVAL(cli->outbuf,smb_vwv0,0); SIVALS(cli->outbuf,smb_vwv1,-1); p = smb_buf(cli->outbuf); *p++ = 4; p += clistr_push(cli, p, path, -1, STR_TERMINATE); cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { return -1; } if (cli_is_error(cli)) { return -1; } /* despite the spec, the result has a -1, followed by length, followed by name */ p = smb_buf(cli->inbuf); p += 4; len = smb_buflen(cli->inbuf) - 4; if (len <= 0) return -1; if (tmp_path) { pstring path2; clistr_pull(cli, path2, p, sizeof(path2), len, STR_ASCII); *tmp_path = strdup(path2); } return SVAL(cli->inbuf,smb_vwv0); }
static int interpret_short_filename(struct cli_state *cli, char *p,file_info *finfo) { *finfo = def_finfo; finfo->cli = cli; finfo->mode = CVAL(p,21); /* this date is converted to GMT by make_unix_date */ finfo->ctime_ts.tv_sec = cli_make_unix_date(cli, p+22); finfo->ctime_ts.tv_nsec = 0; finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec; finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0; finfo->size = IVAL(p,26); clistr_pull(cli, finfo->name, p+30, sizeof(finfo->name), 12, STR_ASCII); if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) { strncpy(finfo->short_name,finfo->name, sizeof(finfo->short_name)-1); finfo->short_name[sizeof(finfo->short_name)-1] = '\0'; } return(DIR_STRUCT_SIZE); }
BOOL cli_qfilename(struct cli_state *cli, int fnum, pstring name) { unsigned int data_len = 0; unsigned int param_len = 0; uint16 setup = TRANSACT2_QFILEINFO; pstring param; char *rparam=NULL, *rdata=NULL; param_len = 4; memset(param, 0, param_len); SSVAL(param, 0, fnum); SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO); 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 */ NULL, data_len, cli->max_xmit /* data, length, max */ )) { return False; } if (!cli_receive_trans(cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len)) { return False; } if (!rdata || data_len < 4) { return False; } clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE); return True; }
BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path, CLIENT_DFS_REFERRAL**refs, size_t *num_refs, uint16 *consumed) { unsigned int data_len = 0; unsigned int param_len = 0; uint16 setup = TRANSACT2_GET_DFS_REFERRAL; char param[sizeof(pstring)+2]; pstring data; char *rparam=NULL, *rdata=NULL; char *p; size_t pathlen = 2*(strlen(path)+1); uint16 num_referrals; CLIENT_DFS_REFERRAL *referrals = NULL; memset(param, 0, sizeof(param)); SSVAL(param, 0, 0x03); /* max referral level */ p = ¶m[2]; p += clistr_push(cli, p, path, MIN(pathlen, sizeof(param)-2), 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 */ (char *)&data, data_len, cli->max_xmit /* data, length, max */ )) { return False; } if (!cli_receive_trans(cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len)) { return False; } *consumed = SVAL( rdata, 0 ); num_referrals = SVAL( rdata, 2 ); if ( num_referrals != 0 ) { uint16 ref_version; uint16 ref_size; int i; uint16 node_offset; referrals = SMB_XMALLOC_ARRAY( CLIENT_DFS_REFERRAL, num_referrals ); /* start at the referrals array */ p = rdata+8; for ( i=0; i<num_referrals; i++ ) { 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 ); clistr_pull( cli, referrals[i].dfspath, p+node_offset, sizeof(referrals[i].dfspath), -1, STR_TERMINATE|STR_UNICODE ); p += ref_size; } } *num_refs = num_referrals; *refs = referrals; SAFE_FREE(rdata); SAFE_FREE(rparam); return True; }
static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,file_info *finfo, uint32 *p_resume_key, DATA_BLOB *p_last_name_raw, uint32 *p_last_name_raw_len) { file_info finfo2; int len; char *base = p; if (!finfo) { finfo = &finfo2; } if (p_resume_key) { *p_resume_key = 0; } memcpy(finfo,&def_finfo,sizeof(*finfo)); finfo->cli = cli; switch (level) { case 1: /* OS/2 understands this */ /* these dates are converted to GMT by make_unix_date */ finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4)); finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8)); finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12)); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); len = CVAL(p, 26); p += 27; p += clistr_align_in(cli, p, 0); /* the len+2 below looks strange but it is important to cope with the differences between win2000 and win9x for this call (tridge) */ p += clistr_pull(cli, finfo->name, p, sizeof(finfo->name), len+2, STR_TERMINATE); return PTR_DIFF(p, base); case 2: /* this is what OS/2 uses mostly */ /* these dates are converted to GMT by make_unix_date */ finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4)); finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8)); finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12)); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); len = CVAL(p, 30); p += 31; /* check for unisys! */ p += clistr_pull(cli, finfo->name, p, sizeof(finfo->name), len, STR_NOALIGN); return PTR_DIFF(p, base) + 1; case 260: /* NT uses this, but also accepts 2 */ { size_t namelen, slen; p += 4; /* next entry offset */ if (p_resume_key) { *p_resume_key = IVAL(p,0); } p += 4; /* fileindex */ /* Offset zero is "create time", not "change time". */ p += 8; finfo->atime_ts = interpret_long_date(p); p += 8; finfo->mtime_ts = interpret_long_date(p); p += 8; finfo->ctime_ts = interpret_long_date(p); p += 8; finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0); p += 8; p += 8; /* alloc size */ finfo->mode = CVAL(p,0); p += 4; namelen = IVAL(p,0); p += 4; p += 4; /* EA size */ slen = SVAL(p, 0); p += 2; { /* stupid NT bugs. grr */ int flags = 0; if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE; clistr_pull(cli, finfo->short_name, p, sizeof(finfo->short_name), slen, flags); } p += 24; /* short name? */ clistr_pull(cli, finfo->name, p, sizeof(finfo->name), namelen, 0); /* To be robust in the face of unicode conversion failures we need to copy the raw bytes of the last name seen here. Namelen doesn't include the terminating unicode null, so copy it here. */ if (p_last_name_raw && p_last_name_raw_len) { if (namelen + 2 > p_last_name_raw->length) { memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length)); *p_last_name_raw_len = 0; } else { memcpy(p_last_name_raw->data, p, namelen); SSVAL(p_last_name_raw->data, namelen, 0); *p_last_name_raw_len = namelen + 2; } } return (size_t)IVAL(base, 0); } } DEBUG(1,("Unknown long filename format %d\n",level)); return (size_t)IVAL(base,0); }
BOOL cli_negprot(struct cli_state *cli) { char *p; int numprots; int plength; memset(cli->outbuf,'\0',smb_size); /* setup the protocol strings */ for (plength=0,numprots=0; prots[numprots].name && prots[numprots].prot<=cli->protocol; numprots++) plength += strlen(prots[numprots].name)+2; set_message(cli->outbuf,0,plength,True); p = smb_buf(cli->outbuf); for (numprots=0; prots[numprots].name && prots[numprots].prot<=cli->protocol; numprots++) { *p++ = 2; p += clistr_push(cli, p, prots[numprots].name, -1, STR_CONVERT|STR_TERMINATE); } SCVAL(cli->outbuf,smb_com,SMBnegprot); cli_setup_packet(cli); SCVAL(smb_buf(cli->outbuf),0,2); cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; show_msg(cli->inbuf); if (cli_is_error(cli) || ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) { return(False); } cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot; if (cli->protocol >= PROTOCOL_NT1) { /* NT protocol */ cli->sec_mode = CVAL(cli->inbuf,smb_vwv1); cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1); cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1); cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1); cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1); cli->serverzone *= 60; /* this time arrives in real GMT */ cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1); memcpy(cli->cryptkey,smb_buf(cli->inbuf),8); cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1); if (cli->capabilities & CAP_RAW_MODE) { cli->readbraw_supported = True; cli->writebraw_supported = True; } /* work out if they sent us a workgroup */ if (smb_buflen(cli->inbuf) > 8) { clistr_pull(cli, cli->server_domain, smb_buf(cli->inbuf)+8, sizeof(cli->server_domain), smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN); } } else if (cli->protocol >= PROTOCOL_LANMAN1) { cli->sec_mode = SVAL(cli->inbuf,smb_vwv1); cli->max_xmit = SVAL(cli->inbuf,smb_vwv2); cli->sesskey = IVAL(cli->inbuf,smb_vwv6); cli->serverzone = SVALS(cli->inbuf,smb_vwv10); cli->serverzone *= 60; /* this time is converted to GMT by make_unix_date */ cli->servertime = make_unix_date(cli->inbuf+smb_vwv8); cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0); cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0); memcpy(cli->cryptkey,smb_buf(cli->inbuf),8); } else { /* the old core protocol */ cli->sec_mode = 0; cli->serverzone = TimeDiff(time(NULL)); } cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE); /* a way to force ascii SMB */ if (getenv("CLI_FORCE_ASCII")) { cli->capabilities &= ~CAP_UNICODE; } return True; }
BOOL cli_send_tconX(struct cli_state *cli, const char *share, const char *dev, const char *pass, int passlen) { fstring fullshare, pword, dos_pword; char *p; memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); fstrcpy(cli->share, share); /* in user level security don't send a password now */ if (cli->sec_mode & 1) { passlen = 1; pass = ""; } if ((cli->sec_mode & 2) && *pass && passlen != 24) { /* * Non-encrypted passwords - convert to DOS codepage before encryption. */ passlen = 24; clistr_push(cli, dos_pword, pass, -1, STR_CONVERT|STR_TERMINATE); SMBencrypt((uchar *)dos_pword,cli->cryptkey,(uchar *)pword); } else { if((cli->sec_mode & 3) == 0) { /* * Non-encrypted passwords - convert to DOS codepage before using. */ passlen = clistr_push(cli, pword, pass, -1, STR_CONVERT|STR_TERMINATE); } else { memcpy(pword, pass, passlen); } } slprintf(fullshare, sizeof(fullshare)-1, "\\\\%s\\%s", cli->desthost, share); set_message(cli->outbuf,4, 0, True); SCVAL(cli->outbuf,smb_com,SMBtconX); cli_setup_packet(cli); SSVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv3,passlen); p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; p += clistr_push(cli, p, fullshare, -1, STR_CONVERT|STR_TERMINATE|STR_UPPER); fstrcpy(p, dev); p += strlen(dev)+1; cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; if (cli_is_error(cli)) { return False; } fstrcpy(cli->dev, "A:"); if (cli->protocol >= PROTOCOL_NT1) { clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE); } if (strcasecmp(share,"IPC$")==0) { fstrcpy(cli->dev, "IPC"); } /* only grab the device if we have a recent protocol level */ if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3) { /* almost certainly win95 - enable bug fixes */ cli->win95 = True; } cli->cnum = SVAL(cli->inbuf,smb_tid); return True; }
static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, const char *pass, int passlen, const char *ntpass, int ntpasslen, const char *workgroup) { uint32 capabilities = cli_session_setup_capabilities(cli); fstring pword, ntpword; char *p; if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) { return False; } if (passlen != 24) { /* non encrypted password supplied. */ passlen = 24; ntpasslen = 24; clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE|STR_CONVERT); clistr_push(cli, ntpword, ntpass, sizeof(ntpword), STR_TERMINATE|STR_CONVERT); SMBencrypt((uchar *)pword,cli->cryptkey,(uchar *)pword); SMBNTencrypt((uchar *)ntpword,cli->cryptkey,(uchar *)ntpword); } else { memcpy(pword, pass, passlen); memcpy(ntpword, ntpass, ntpasslen); } /* send a session setup command */ memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,13,0,True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); cli_setup_packet(cli); SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); SSVAL(cli->outbuf,smb_vwv3,2); SSVAL(cli->outbuf,smb_vwv4,cli->pid); SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); SSVAL(cli->outbuf,smb_vwv8,ntpasslen); SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; memcpy(p,ntpword,ntpasslen); p += ntpasslen; p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER|STR_CONVERT); p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER|STR_CONVERT); p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE|STR_CONVERT); p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE|STR_CONVERT); cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; show_msg(cli->inbuf); if (cli_is_error(cli)) { return False; } /* use the returned vuid from now on */ cli->vuid = SVAL(cli->inbuf,smb_uid); p = smb_buf(cli->inbuf); p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); fstrcpy(cli->user_name, user); return True; }
static size_t interpret_long_filename(TALLOC_CTX *ctx, struct cli_state *cli, int level, const char *base_ptr, uint16_t recv_flags2, const char *p, const char *pdata_end, struct file_info *finfo, uint32 *p_resume_key, DATA_BLOB *p_last_name_raw) { int len; size_t ret; const char *base = p; data_blob_free(p_last_name_raw); if (p_resume_key) { *p_resume_key = 0; } ZERO_STRUCTP(finfo); switch (level) { case SMB_FIND_INFO_STANDARD: /* OS/2 understands this */ /* these dates are converted to GMT by make_unix_date */ if (pdata_end - base < 27) { return pdata_end - base; } finfo->ctime_ts = convert_time_t_to_timespec( make_unix_date2(p+4, cli->serverzone)); finfo->atime_ts = convert_time_t_to_timespec( make_unix_date2(p+8, cli->serverzone)); finfo->mtime_ts = convert_time_t_to_timespec( make_unix_date2(p+12, cli->serverzone)); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); len = CVAL(p, 26); p += 27; p += align_string(base_ptr, p, 0); /* We can safely use len here (which is required by OS/2) * and the NAS-BASIC server instead of +2 or +1 as the * STR_TERMINATE flag below is * actually used as the length calculation. * The len is merely an upper bound. * Due to the explicit 2 byte null termination * in cli_receive_trans/cli_receive_nt_trans * we know this is safe. JRA + kukks */ if (p + len > pdata_end) { return pdata_end - base; } /* the len+2 below looks strange but it is important to cope with the differences between win2000 and win9x for this call (tridge) */ ret = clistr_pull_talloc(ctx, base_ptr, recv_flags2, &finfo->name, p, len+2, STR_TERMINATE); if (ret == (size_t)-1) { return pdata_end - base; } p += ret; return PTR_DIFF(p, base); case SMB_FIND_EA_SIZE: /* this is what OS/2 uses mostly */ /* these dates are converted to GMT by make_unix_date */ if (pdata_end - base < 31) { return pdata_end - base; } finfo->ctime_ts = convert_time_t_to_timespec( make_unix_date2(p+4, cli->serverzone)); finfo->atime_ts = convert_time_t_to_timespec( make_unix_date2(p+8, cli->serverzone)); finfo->mtime_ts = convert_time_t_to_timespec( make_unix_date2(p+12, cli->serverzone)); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); len = CVAL(p, 30); p += 31; /* check for unisys! */ if (p + len + 1 > pdata_end) { return pdata_end - base; } ret = clistr_pull_talloc(ctx, base_ptr, recv_flags2, &finfo->name, p, len, STR_NOALIGN); if (ret == (size_t)-1) { return pdata_end - base; } p += ret; return PTR_DIFF(p, base) + 1; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: /* NT uses this, but also accepts 2 */ { size_t namelen, slen; if (pdata_end - base < 94) { return pdata_end - base; } p += 4; /* next entry offset */ if (p_resume_key) { *p_resume_key = IVAL(p,0); } p += 4; /* fileindex */ /* Offset zero is "create time", not "change time". */ p += 8; finfo->atime_ts = interpret_long_date(p); p += 8; finfo->mtime_ts = interpret_long_date(p); p += 8; finfo->ctime_ts = interpret_long_date(p); p += 8; finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0); p += 8; p += 8; /* alloc size */ finfo->mode = CVAL(p,0); p += 4; namelen = IVAL(p,0); p += 4; p += 4; /* EA size */ slen = SVAL(p, 0); if (slen > 24) { /* Bad short name length. */ return pdata_end - base; } p += 2; { /* stupid NT bugs. grr */ int flags = 0; if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE; clistr_pull(base_ptr, finfo->short_name, p, sizeof(finfo->short_name), slen, flags); } p += 24; /* short name? */ if (p + namelen < p || p + namelen > pdata_end) { return pdata_end - base; } ret = clistr_pull_talloc(ctx, base_ptr, recv_flags2, &finfo->name, p, namelen, 0); if (ret == (size_t)-1) { return pdata_end - base; } /* To be robust in the face of unicode conversion failures we need to copy the raw bytes of the last name seen here. Namelen doesn't include the terminating unicode null, so copy it here. */ if (p_last_name_raw) { *p_last_name_raw = data_blob(NULL, namelen+2); memcpy(p_last_name_raw->data, p, namelen); SSVAL(p_last_name_raw->data, namelen, 0); } return calc_next_entry_offset(base, pdata_end); } } DEBUG(1,("Unknown long filename format %d\n",level)); return calc_next_entry_offset(base, pdata_end); }