ssize_t message_push_string(uint8 **outbuf, const char *str, int flags) { size_t buf_size = smb_len(*outbuf) + 4; size_t grow_size; size_t result = 0; uint8 *tmp; NTSTATUS status; /* * We need to over-allocate, now knowing what srvstr_push will * actually use. This is very generous by incorporating potential * padding, the terminating 0 and at most 4 chars per UTF-16 code * point. */ grow_size = (strlen(str) + 2) * 4; if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, buf_size + grow_size))) { DEBUG(0, ("talloc failed\n")); return -1; } status = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2), tmp + buf_size, str, grow_size, flags, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("srvstr_push failed\n")); return -1; } set_message_bcc((char *)tmp, smb_buflen(tmp) + result); *outbuf = tmp; return result; }
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); }
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; }