Apply some const
[Samba/gebeck_regimport.git] / source / libsmb / clirap.c
blob98066629d184c5be1ba57b8c37b97519610233e3
1 /*
2 Unix SMB/CIFS implementation.
3 client RAP calls
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #define NO_SYSLOG
23 #include "includes.h"
26 /****************************************************************************
27 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
28 ****************************************************************************/
29 BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name,
30 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
31 char *params, uint32 param_count, uint32 max_param_count,
32 char *data, uint32 data_count, uint32 max_data_count,
33 char **rparam, uint32 *rparam_count,
34 char **rdata, uint32 *rdata_count)
36 cli_send_trans(cli, SMBtrans,
37 pipe_name,
38 0,0, /* fid, flags */
39 setup, setup_count, max_setup_count,
40 params, param_count, max_param_count,
41 data, data_count, max_data_count);
43 return (cli_receive_trans(cli, SMBtrans,
44 rparam, (unsigned int *)rparam_count,
45 rdata, (unsigned int *)rdata_count));
48 /****************************************************************************
49 call a remote api
50 ****************************************************************************/
51 BOOL cli_api(struct cli_state *cli,
52 char *param, int prcnt, int mprcnt,
53 char *data, int drcnt, int mdrcnt,
54 char **rparam, unsigned int *rprcnt,
55 char **rdata, unsigned int *rdrcnt)
57 cli_send_trans(cli,SMBtrans,
58 PIPE_LANMAN, /* Name */
59 0,0, /* fid, flags */
60 NULL,0,0, /* Setup, length, max */
61 param, prcnt, mprcnt, /* Params, length, max */
62 data, drcnt, mdrcnt /* Data, length, max */
65 return (cli_receive_trans(cli,SMBtrans,
66 rparam, rprcnt,
67 rdata, rdrcnt));
71 /****************************************************************************
72 perform a NetWkstaUserLogon
73 ****************************************************************************/
74 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
76 char *rparam = NULL;
77 char *rdata = NULL;
78 char *p;
79 unsigned int rdrcnt,rprcnt;
80 pstring param;
82 memset(param, 0, sizeof(param));
84 /* send a SMBtrans command with api NetWkstaUserLogon */
85 p = param;
86 SSVAL(p,0,132); /* api number */
87 p += 2;
88 pstrcpy_base(p,"OOWb54WrLh",param);
89 p = skip_string(p,1);
90 pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
91 p = skip_string(p,1);
92 SSVAL(p,0,1);
93 p += 2;
94 pstrcpy_base(p,user,param);
95 strupper_m(p);
96 p += 21;
97 p++;
98 p += 15;
99 p++;
100 pstrcpy_base(p, workstation, param);
101 strupper_m(p);
102 p += 16;
103 SSVAL(p, 0, CLI_BUFFER_SIZE);
104 p += 2;
105 SSVAL(p, 0, CLI_BUFFER_SIZE);
106 p += 2;
108 if (cli_api(cli,
109 param, PTR_DIFF(p,param),1024, /* param, length, max */
110 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
111 &rparam, &rprcnt, /* return params, return size */
112 &rdata, &rdrcnt /* return data, return size */
113 )) {
114 cli->rap_error = rparam? SVAL(rparam,0) : -1;
115 p = rdata;
117 if (cli->rap_error == 0) {
118 DEBUG(4,("NetWkstaUserLogon success\n"));
119 cli->privileges = SVAL(p, 24);
120 /* The cli->eff_name field used to be set here
121 but it wasn't used anywhere else. */
122 } else {
123 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
127 SAFE_FREE(rparam);
128 SAFE_FREE(rdata);
129 return (cli->rap_error == 0);
132 /****************************************************************************
133 call a NetShareEnum - try and browse available connections on a host
134 ****************************************************************************/
135 int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
137 char *rparam = NULL;
138 char *rdata = NULL;
139 char *p;
140 unsigned int rdrcnt,rprcnt;
141 pstring param;
142 int count = -1;
144 /* now send a SMBtrans command with api RNetShareEnum */
145 p = param;
146 SSVAL(p,0,0); /* api number */
147 p += 2;
148 pstrcpy_base(p,"WrLeh",param);
149 p = skip_string(p,1);
150 pstrcpy_base(p,"B13BWz",param);
151 p = skip_string(p,1);
152 SSVAL(p,0,1);
154 * Win2k needs a *smaller* buffer than 0xFFFF here -
155 * it returns "out of server memory" with 0xFFFF !!! JRA.
157 SSVAL(p,2,0xFFE0);
158 p += 4;
160 if (cli_api(cli,
161 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
162 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
163 &rparam, &rprcnt, /* return params, length */
164 &rdata, &rdrcnt)) /* return data, length */
166 int res = rparam? SVAL(rparam,0) : -1;
168 if (res == 0 || res == ERRmoredata) {
169 int converter=SVAL(rparam,2);
170 int i;
172 count=SVAL(rparam,4);
173 p = rdata;
175 for (i=0;i<count;i++,p+=20) {
176 char *sname = p;
177 int type = SVAL(p,14);
178 int comment_offset = IVAL(p,16) & 0xFFFF;
179 const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
180 pstring s1, s2;
182 pull_ascii_pstring(s1, sname);
183 pull_ascii_pstring(s2, cmnt);
185 fn(s1, type, s2, state);
187 } else {
188 DEBUG(4,("NetShareEnum res=%d\n", res));
190 } else {
191 DEBUG(4,("NetShareEnum failed\n"));
194 SAFE_FREE(rparam);
195 SAFE_FREE(rdata);
197 return count;
201 /****************************************************************************
202 call a NetServerEnum for the specified workgroup and servertype mask. This
203 function then calls the specified callback function for each name returned.
205 The callback function takes 4 arguments: the machine name, the server type,
206 the comment and a state pointer.
207 ****************************************************************************/
208 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
209 void (*fn)(const char *, uint32, const char *,
210 const void *),
211 const void *state)
213 char *rparam = NULL;
214 char *rdata = NULL;
215 unsigned int rdrcnt,rprcnt;
216 char *p;
217 pstring param;
218 int uLevel = 1;
219 int count = -1;
221 /* send a SMBtrans command with api NetServerEnum */
222 p = param;
223 SSVAL(p,0,0x68); /* api number */
224 p += 2;
225 pstrcpy_base(p,"WrLehDz", param);
226 p = skip_string(p,1);
228 pstrcpy_base(p,"B16BBDz", param);
230 p = skip_string(p,1);
231 SSVAL(p,0,uLevel);
232 SSVAL(p,2,CLI_BUFFER_SIZE);
233 p += 4;
234 SIVAL(p,0,stype);
235 p += 4;
237 p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
239 if (cli_api(cli,
240 param, PTR_DIFF(p,param), 8, /* params, length, max */
241 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
242 &rparam, &rprcnt, /* return params, return size */
243 &rdata, &rdrcnt /* return data, return size */
244 )) {
245 int res = rparam? SVAL(rparam,0) : -1;
247 if (res == 0 || res == ERRmoredata) {
248 int i;
249 int converter=SVAL(rparam,2);
251 count=SVAL(rparam,4);
252 p = rdata;
254 for (i = 0;i < count;i++, p += 26) {
255 char *sname = p;
256 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
257 const char *cmnt = comment_offset?(rdata+comment_offset):"";
258 pstring s1, s2;
260 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
262 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
264 pull_ascii_pstring(s1, sname);
265 pull_ascii_pstring(s2, cmnt);
266 fn(s1, stype, s2, state);
271 SAFE_FREE(rparam);
272 SAFE_FREE(rdata);
274 return(count > 0);
279 /****************************************************************************
280 Send a SamOEMChangePassword command
281 ****************************************************************************/
282 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
283 const char *old_password)
285 pstring param;
286 char data[532];
287 char *p = param;
288 unsigned char old_pw_hash[16];
289 unsigned char new_pw_hash[16];
290 unsigned int data_len;
291 unsigned int param_len = 0;
292 char *rparam = NULL;
293 char *rdata = NULL;
294 unsigned int rprcnt, rdrcnt;
296 if (strlen(user) >= sizeof(fstring)-1) {
297 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
298 return False;
301 SSVAL(p,0,214); /* SamOEMChangePassword command. */
302 p += 2;
303 pstrcpy_base(p, "zsT", param);
304 p = skip_string(p,1);
305 pstrcpy_base(p, "B516B16", param);
306 p = skip_string(p,1);
307 pstrcpy_base(p,user, param);
308 p = skip_string(p,1);
309 SSVAL(p,0,532);
310 p += 2;
312 param_len = PTR_DIFF(p,param);
315 * Get the Lanman hash of the old password, we
316 * use this as the key to make_oem_passwd_hash().
318 E_deshash(old_password, old_pw_hash);
320 encode_pw_buffer(data, new_password, STR_ASCII);
322 #ifdef DEBUG_PASSWORD
323 DEBUG(100,("make_oem_passwd_hash\n"));
324 dump_data(100, data, 516);
325 #endif
326 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
329 * Now place the old password hash in the data.
331 E_deshash(new_password, new_pw_hash);
333 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
335 data_len = 532;
337 if (cli_send_trans(cli,SMBtrans,
338 PIPE_LANMAN, /* name */
339 0,0, /* fid, flags */
340 NULL,0,0, /* setup, length, max */
341 param,param_len,2, /* param, length, max */
342 data,data_len,0 /* data, length, max */
343 ) == False) {
344 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
345 user ));
346 return False;
349 if (!cli_receive_trans(cli,SMBtrans,
350 &rparam, &rprcnt,
351 &rdata, &rdrcnt)) {
352 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
353 user ));
354 return False;
357 if (rparam)
358 cli->rap_error = SVAL(rparam,0);
360 SAFE_FREE(rparam);
361 SAFE_FREE(rdata);
363 return (cli->rap_error == 0);
367 /****************************************************************************
368 send a qpathinfo call
369 ****************************************************************************/
370 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
371 time_t *c_time, time_t *a_time, time_t *m_time,
372 size_t *size, uint16 *mode)
374 unsigned int data_len = 0;
375 unsigned int param_len = 0;
376 unsigned int rparam_len, rdata_len;
377 uint16 setup = TRANSACT2_QPATHINFO;
378 pstring param;
379 char *rparam=NULL, *rdata=NULL;
380 int count=8;
381 BOOL ret;
382 time_t (*date_fn)(void *);
383 char *p;
385 p = param;
386 memset(p, 0, 6);
387 SSVAL(p, 0, SMB_INFO_STANDARD);
388 p += 6;
389 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
391 param_len = PTR_DIFF(p, param);
393 do {
394 ret = (cli_send_trans(cli, SMBtrans2,
395 NULL, /* Name */
396 -1, 0, /* fid, flags */
397 &setup, 1, 0, /* setup, length, max */
398 param, param_len, 10, /* param, length, max */
399 NULL, data_len, cli->max_xmit /* data, length, max */
400 ) &&
401 cli_receive_trans(cli, SMBtrans2,
402 &rparam, &rparam_len,
403 &rdata, &rdata_len));
404 if (!cli_is_dos_error(cli)) break;
405 if (!ret) {
406 /* we need to work around a Win95 bug - sometimes
407 it gives ERRSRV/ERRerror temprarily */
408 uint8 eclass;
409 uint32 ecode;
410 cli_dos_error(cli, &eclass, &ecode);
411 if (eclass != ERRSRV || ecode != ERRerror) break;
412 smb_msleep(100);
414 } while (count-- && ret==False);
416 if (!ret || !rdata || rdata_len < 22) {
417 return False;
420 if (cli->win95) {
421 date_fn = make_unix_date;
422 } else {
423 date_fn = make_unix_date2;
426 if (c_time) {
427 *c_time = date_fn(rdata+0);
429 if (a_time) {
430 *a_time = date_fn(rdata+4);
432 if (m_time) {
433 *m_time = date_fn(rdata+8);
435 if (size) {
436 *size = IVAL(rdata, 12);
438 if (mode) {
439 *mode = SVAL(rdata,l1_attrFile);
442 SAFE_FREE(rdata);
443 SAFE_FREE(rparam);
444 return True;
447 /****************************************************************************
448 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
449 ****************************************************************************/
450 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
451 time_t *c_time, time_t *a_time, time_t *m_time,
452 time_t *w_time, size_t *size, uint16 *mode,
453 SMB_INO_T *ino)
455 unsigned int data_len = 0;
456 unsigned int param_len = 0;
457 uint16 setup = TRANSACT2_QPATHINFO;
458 pstring param;
459 char *rparam=NULL, *rdata=NULL;
460 char *p;
462 p = param;
463 memset(p, 0, 6);
464 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
465 p += 6;
466 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
468 param_len = PTR_DIFF(p, param);
470 if (!cli_send_trans(cli, SMBtrans2,
471 NULL, /* name */
472 -1, 0, /* fid, flags */
473 &setup, 1, 0, /* setup, length, max */
474 param, param_len, 10, /* param, length, max */
475 NULL, data_len, cli->max_xmit /* data, length, max */
476 )) {
477 return False;
480 if (!cli_receive_trans(cli, SMBtrans2,
481 &rparam, &param_len,
482 &rdata, &data_len)) {
483 return False;
486 if (!rdata || data_len < 22) {
487 return False;
490 if (c_time) {
491 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
493 if (a_time) {
494 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
496 if (m_time) {
497 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
499 if (w_time) {
500 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
502 if (mode) {
503 *mode = SVAL(rdata, 32);
505 if (size) {
506 *size = IVAL(rdata, 48);
508 if (ino) {
509 *ino = IVAL(rdata, 64);
512 SAFE_FREE(rdata);
513 SAFE_FREE(rparam);
514 return True;
518 /****************************************************************************
519 send a qfileinfo QUERY_FILE_NAME_INFO call
520 ****************************************************************************/
521 BOOL cli_qfilename(struct cli_state *cli, int fnum,
522 pstring name)
524 unsigned int data_len = 0;
525 unsigned int param_len = 0;
526 uint16 setup = TRANSACT2_QFILEINFO;
527 pstring param;
528 char *rparam=NULL, *rdata=NULL;
530 param_len = 4;
531 memset(param, 0, param_len);
532 SSVAL(param, 0, fnum);
533 SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
535 if (!cli_send_trans(cli, SMBtrans2,
536 NULL, /* name */
537 -1, 0, /* fid, flags */
538 &setup, 1, 0, /* setup, length, max */
539 param, param_len, 2, /* param, length, max */
540 NULL, data_len, cli->max_xmit /* data, length, max */
541 )) {
542 return False;
545 if (!cli_receive_trans(cli, SMBtrans2,
546 &rparam, &param_len,
547 &rdata, &data_len)) {
548 return False;
551 if (!rdata || data_len < 4) {
552 return False;
555 clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
557 return True;
561 /****************************************************************************
562 send a qfileinfo call
563 ****************************************************************************/
564 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
565 uint16 *mode, size_t *size,
566 time_t *c_time, time_t *a_time, time_t *m_time,
567 time_t *w_time, SMB_INO_T *ino)
569 unsigned int data_len = 0;
570 unsigned int param_len = 0;
571 uint16 setup = TRANSACT2_QFILEINFO;
572 pstring param;
573 char *rparam=NULL, *rdata=NULL;
575 /* if its a win95 server then fail this - win95 totally screws it
576 up */
577 if (cli->win95) return False;
579 param_len = 4;
581 memset(param, 0, param_len);
582 SSVAL(param, 0, fnum);
583 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
585 if (!cli_send_trans(cli, SMBtrans2,
586 NULL, /* name */
587 -1, 0, /* fid, flags */
588 &setup, 1, 0, /* setup, length, max */
589 param, param_len, 2, /* param, length, max */
590 NULL, data_len, cli->max_xmit /* data, length, max */
591 )) {
592 return False;
595 if (!cli_receive_trans(cli, SMBtrans2,
596 &rparam, &param_len,
597 &rdata, &data_len)) {
598 return False;
601 if (!rdata || data_len < 68) {
602 return False;
605 if (c_time) {
606 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
608 if (a_time) {
609 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
611 if (m_time) {
612 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
614 if (w_time) {
615 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
617 if (mode) {
618 *mode = SVAL(rdata, 32);
620 if (size) {
621 *size = IVAL(rdata, 48);
623 if (ino) {
624 *ino = IVAL(rdata, 64);
627 SAFE_FREE(rdata);
628 SAFE_FREE(rparam);
629 return True;
632 /****************************************************************************
633 send a qfileinfo call
634 ****************************************************************************/
635 BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
637 unsigned int data_len = 0;
638 unsigned int param_len = 0;
639 uint16 setup = TRANSACT2_QFILEINFO;
640 pstring param;
641 char *rparam=NULL, *rdata=NULL;
643 *poutdata = NULL;
644 *poutlen = 0;
646 /* if its a win95 server then fail this - win95 totally screws it
647 up */
648 if (cli->win95)
649 return False;
651 param_len = 4;
653 memset(param, 0, param_len);
654 SSVAL(param, 0, fnum);
655 SSVAL(param, 2, level);
657 if (!cli_send_trans(cli, SMBtrans2,
658 NULL, /* name */
659 -1, 0, /* fid, flags */
660 &setup, 1, 0, /* setup, length, max */
661 param, param_len, 2, /* param, length, max */
662 NULL, data_len, cli->max_xmit /* data, length, max */
663 )) {
664 return False;
667 if (!cli_receive_trans(cli, SMBtrans2,
668 &rparam, &param_len,
669 &rdata, &data_len)) {
670 return False;
673 *poutdata = memdup(rdata, data_len);
674 *poutlen = data_len;
676 SAFE_FREE(rdata);
677 SAFE_FREE(rparam);
678 return True;
683 /****************************************************************************
684 send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
685 ****************************************************************************/
686 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
688 unsigned int data_len = 0;
689 unsigned int param_len = 0;
690 uint16 setup = TRANSACT2_QPATHINFO;
691 pstring param;
692 char *rparam=NULL, *rdata=NULL;
693 int count=8;
694 char *p;
695 BOOL ret;
696 unsigned int len;
698 p = param;
699 memset(p, 0, 6);
700 SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
701 p += 6;
702 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
704 param_len = PTR_DIFF(p, param);
706 do {
707 ret = (cli_send_trans(cli, SMBtrans2,
708 NULL, /* Name */
709 -1, 0, /* fid, flags */
710 &setup, 1, 0, /* setup, length, max */
711 param, param_len, 10, /* param, length, max */
712 NULL, data_len, cli->max_xmit /* data, length, max */
713 ) &&
714 cli_receive_trans(cli, SMBtrans2,
715 &rparam, &param_len,
716 &rdata, &data_len));
717 if (!ret && cli_is_dos_error(cli)) {
718 /* we need to work around a Win95 bug - sometimes
719 it gives ERRSRV/ERRerror temprarily */
720 uint8 eclass;
721 uint32 ecode;
722 cli_dos_error(cli, &eclass, &ecode);
723 if (eclass != ERRSRV || ecode != ERRerror) break;
724 smb_msleep(100);
726 } while (count-- && ret==False);
728 if (!ret || !rdata || data_len < 4) {
729 return NT_STATUS_UNSUCCESSFUL;
732 len = IVAL(rdata, 0);
734 if (len > data_len - 4) {
735 return NT_STATUS_INVALID_NETWORK_RESPONSE;
738 clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
740 SAFE_FREE(rdata);
741 SAFE_FREE(rparam);
743 return NT_STATUS_OK;