this now works as a add|delete share command :-)
[Samba.git] / source / libsmb / clirap.c
blob561d717e730346aafa3e41230b9218d0aba0d87e
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 client RAP calls
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define NO_SYSLOG
24 #include "includes.h"
27 /****************************************************************************
28 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
29 ****************************************************************************/
30 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name,
31 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
32 char *params, uint32 param_count, uint32 max_param_count,
33 char *data, uint32 data_count, uint32 max_data_count,
34 char **rparam, uint32 *rparam_count,
35 char **rdata, uint32 *rdata_count)
37 cli_send_trans(cli, SMBtrans,
38 pipe_name,
39 0,0, /* fid, flags */
40 setup, setup_count, max_setup_count,
41 params, param_count, max_param_count,
42 data, data_count, max_data_count);
44 return (cli_receive_trans(cli, SMBtrans,
45 rparam, (int *)rparam_count,
46 rdata, (int *)rdata_count));
49 /****************************************************************************
50 call a remote api
51 ****************************************************************************/
52 BOOL cli_api(struct cli_state *cli,
53 char *param, int prcnt, int mprcnt,
54 char *data, int drcnt, int mdrcnt,
55 char **rparam, int *rprcnt,
56 char **rdata, int *rdrcnt)
58 cli_send_trans(cli,SMBtrans,
59 PIPE_LANMAN, /* Name */
60 0,0, /* fid, flags */
61 NULL,0,0, /* Setup, length, max */
62 param, prcnt, mprcnt, /* Params, length, max */
63 data, drcnt, mdrcnt /* Data, length, max */
66 return (cli_receive_trans(cli,SMBtrans,
67 rparam, rprcnt,
68 rdata, rdrcnt));
72 /****************************************************************************
73 perform a NetWkstaUserLogon
74 ****************************************************************************/
75 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
77 char *rparam = NULL;
78 char *rdata = NULL;
79 char *p;
80 int rdrcnt,rprcnt;
81 pstring param;
83 memset(param, 0, sizeof(param));
85 /* send a SMBtrans command with api NetWkstaUserLogon */
86 p = param;
87 SSVAL(p,0,132); /* api number */
88 p += 2;
89 pstrcpy(p,"OOWb54WrLh");
90 p = skip_string(p,1);
91 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
92 p = skip_string(p,1);
93 SSVAL(p,0,1);
94 p += 2;
95 pstrcpy(p,user);
96 strupper(p);
97 p += 21;
98 p++;
99 p += 15;
100 p++;
101 pstrcpy(p, workstation);
102 strupper(p);
103 p += 16;
104 SSVAL(p, 0, CLI_BUFFER_SIZE);
105 p += 2;
106 SSVAL(p, 0, CLI_BUFFER_SIZE);
107 p += 2;
109 if (cli_api(cli,
110 param, PTR_DIFF(p,param),1024, /* param, length, max */
111 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
112 &rparam, &rprcnt, /* return params, return size */
113 &rdata, &rdrcnt /* return data, return size */
114 )) {
115 cli->rap_error = rparam? SVAL(rparam,0) : -1;
116 p = rdata;
118 if (cli->rap_error == 0) {
119 DEBUG(4,("NetWkstaUserLogon success\n"));
120 cli->privileges = SVAL(p, 24);
121 fstrcpy(cli->eff_name,p+2);
122 } else {
123 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
127 if (rparam)
128 free(rparam);
129 if (rdata)
130 free(rdata);
131 return (cli->rap_error == 0);
134 /****************************************************************************
135 call a NetShareEnum - try and browse available connections on a host
136 ****************************************************************************/
137 int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
139 char *rparam = NULL;
140 char *rdata = NULL;
141 char *p;
142 int rdrcnt,rprcnt;
143 pstring param;
144 int count = -1;
146 /* now send a SMBtrans command with api RNetShareEnum */
147 p = param;
148 SSVAL(p,0,0); /* api number */
149 p += 2;
150 pstrcpy(p,"WrLeh");
151 p = skip_string(p,1);
152 pstrcpy(p,"B13BWz");
153 p = skip_string(p,1);
154 SSVAL(p,0,1);
156 * Win2k needs a *smaller* buffer than 0xFFFF here -
157 * it returns "out of server memory" with 0xFFFF !!! JRA.
159 SSVAL(p,2,0xFFE0);
160 p += 4;
162 if (cli_api(cli,
163 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
164 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
165 &rparam, &rprcnt, /* return params, length */
166 &rdata, &rdrcnt)) /* return data, length */
168 int res = rparam? SVAL(rparam,0) : -1;
170 if (res == 0 || res == ERRmoredata) {
171 int converter=SVAL(rparam,2);
172 int i;
174 count=SVAL(rparam,4);
175 p = rdata;
177 for (i=0;i<count;i++,p+=20) {
178 char *sname = p;
179 int type = SVAL(p,14);
180 int comment_offset = IVAL(p,16) & 0xFFFF;
181 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
182 dos_to_unix(sname,True);
183 dos_to_unix(cmnt,True);
184 fn(sname, type, cmnt, state);
186 } else {
187 DEBUG(4,("NetShareEnum res=%d\n", res));
189 } else {
190 DEBUG(4,("NetShareEnum failed\n"));
193 if (rparam)
194 free(rparam);
195 if (rdata)
196 free(rdata);
198 return count;
202 /****************************************************************************
203 call a NetServerEnum for the specified workgroup and servertype mask.
204 This function then calls the specified callback function for each name returned.
206 The callback function takes 3 arguments: the machine name, the server type and
207 the comment.
208 ****************************************************************************/
209 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
210 void (*fn)(const char *, uint32, const char *, void *),
211 void *state)
213 char *rparam = NULL;
214 char *rdata = NULL;
215 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(p,"WrLehDz");
226 p = skip_string(p,1);
228 pstrcpy(p,"B16BBDz");
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 += clistr_push(cli, p, workgroup, -1,
238 STR_TERMINATE | STR_CONVERT | STR_ASCII);
240 if (cli_api(cli,
241 param, PTR_DIFF(p,param), 8, /* params, length, max */
242 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
243 &rparam, &rprcnt, /* return params, return size */
244 &rdata, &rdrcnt /* return data, return size */
245 )) {
246 int res = rparam? SVAL(rparam,0) : -1;
248 if (res == 0 || res == ERRmoredata) {
249 int i;
250 int converter=SVAL(rparam,2);
252 count=SVAL(rparam,4);
253 p = rdata;
255 for (i = 0;i < count;i++, p += 26) {
256 char *sname = p;
257 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
258 char *cmnt = comment_offset?(rdata+comment_offset):"";
259 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
261 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
263 dos_to_unix(sname, True);
264 dos_to_unix(cmnt, True);
265 fn(sname, stype, cmnt, state);
270 if (rparam)
271 free(rparam);
272 if (rdata)
273 free(rdata);
275 return(count > 0);
280 /****************************************************************************
281 Send a SamOEMChangePassword command
282 ****************************************************************************/
283 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
284 const char *old_password)
286 char param[16+sizeof(fstring)];
287 char data[532];
288 char *p = param;
289 fstring upper_case_old_pw;
290 fstring upper_case_new_pw;
291 unsigned char old_pw_hash[16];
292 unsigned char new_pw_hash[16];
293 int data_len;
294 int param_len = 0;
295 char *rparam = NULL;
296 char *rdata = NULL;
297 int rprcnt, rdrcnt;
298 pstring dos_new_password;
300 if (strlen(user) >= sizeof(fstring)-1) {
301 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
302 return False;
305 SSVAL(p,0,214); /* SamOEMChangePassword command. */
306 p += 2;
307 pstrcpy(p, "zsT");
308 p = skip_string(p,1);
309 pstrcpy(p, "B516B16");
310 p = skip_string(p,1);
311 pstrcpy(p,user);
312 p = skip_string(p,1);
313 SSVAL(p,0,532);
314 p += 2;
316 param_len = PTR_DIFF(p,param);
319 * Get the Lanman hash of the old password, we
320 * use this as the key to make_oem_passwd_hash().
322 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
323 fstrcpy(upper_case_old_pw, old_password);
324 unix_to_dos(upper_case_old_pw,True);
325 strupper(upper_case_old_pw);
326 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
328 pstrcpy(dos_new_password, new_password);
329 unix_to_dos(dos_new_password, True);
331 if (!make_oem_passwd_hash( data, dos_new_password, old_pw_hash, False))
332 return False;
335 * Now place the old password hash in the data.
337 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
338 fstrcpy(upper_case_new_pw, new_password);
339 unix_to_dos(upper_case_new_pw,True);
340 strupper(upper_case_new_pw);
342 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
344 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
346 data_len = 532;
348 if (cli_send_trans(cli,SMBtrans,
349 PIPE_LANMAN, /* name */
350 0,0, /* fid, flags */
351 NULL,0,0, /* setup, length, max */
352 param,param_len,2, /* param, length, max */
353 data,data_len,0 /* data, length, max */
354 ) == False) {
355 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
356 user ));
357 return False;
360 if (cli_receive_trans(cli,SMBtrans,
361 &rparam, &rprcnt,
362 &rdata, &rdrcnt)) {
363 if (rparam)
364 cli->rap_error = SVAL(rparam,0);
367 if (rparam)
368 free(rparam);
369 if (rdata)
370 free(rdata);
372 return (cli->rap_error == 0);
376 /****************************************************************************
377 send a qpathinfo call
378 ****************************************************************************/
379 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
380 time_t *c_time, time_t *a_time, time_t *m_time,
381 size_t *size, uint16 *mode)
383 int data_len = 0;
384 int param_len = 0;
385 uint16 setup = TRANSACT2_QPATHINFO;
386 pstring param;
387 char *rparam=NULL, *rdata=NULL;
388 int count=8;
389 BOOL ret;
390 time_t (*date_fn)(void *);
391 char *p;
393 p = param;
394 memset(p, 0, 6);
395 SSVAL(p, 0, SMB_INFO_STANDARD);
396 p += 6;
397 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE | STR_CONVERT);
399 param_len = PTR_DIFF(p, param);
401 do {
402 ret = (cli_send_trans(cli, SMBtrans2,
403 NULL, /* Name */
404 -1, 0, /* fid, flags */
405 &setup, 1, 0, /* setup, length, max */
406 param, param_len, 10, /* param, length, max */
407 NULL, data_len, cli->max_xmit /* data, length, max */
408 ) &&
409 cli_receive_trans(cli, SMBtrans2,
410 &rparam, &param_len,
411 &rdata, &data_len));
412 if (!ret) {
413 /* we need to work around a Win95 bug - sometimes
414 it gives ERRSRV/ERRerror temprarily */
415 uint8 eclass;
416 uint32 ecode;
417 cli_error(cli, &eclass, &ecode, NULL);
418 if (eclass != ERRSRV || ecode != ERRerror) break;
419 msleep(100);
421 } while (count-- && ret==False);
423 if (!ret || !rdata || data_len < 22) {
424 return False;
427 if (cli->win95) {
428 date_fn = make_unix_date;
429 } else {
430 date_fn = make_unix_date2;
433 if (c_time) {
434 *c_time = date_fn(rdata+0);
436 if (a_time) {
437 *a_time = date_fn(rdata+4);
439 if (m_time) {
440 *m_time = date_fn(rdata+8);
442 if (size) {
443 *size = IVAL(rdata, 12);
445 if (mode) {
446 *mode = SVAL(rdata,l1_attrFile);
449 if (rdata) free(rdata);
450 if (rparam) free(rparam);
451 return True;
454 /****************************************************************************
455 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
456 ****************************************************************************/
457 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
458 time_t *c_time, time_t *a_time, time_t *m_time,
459 time_t *w_time, size_t *size, uint16 *mode,
460 SMB_INO_T *ino)
462 int data_len = 0;
463 int param_len = 0;
464 uint16 setup = TRANSACT2_QPATHINFO;
465 pstring param;
466 char *rparam=NULL, *rdata=NULL;
467 char *p;
469 p = param;
470 memset(p, 0, 6);
471 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
472 p += 6;
473 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE | STR_CONVERT);
475 param_len = PTR_DIFF(p, param);
477 if (!cli_send_trans(cli, SMBtrans2,
478 NULL, /* name */
479 -1, 0, /* fid, flags */
480 &setup, 1, 0, /* setup, length, max */
481 param, param_len, 10, /* param, length, max */
482 NULL, data_len, cli->max_xmit /* data, length, max */
483 )) {
484 return False;
487 if (!cli_receive_trans(cli, SMBtrans2,
488 &rparam, &param_len,
489 &rdata, &data_len)) {
490 return False;
493 if (!rdata || data_len < 22) {
494 return False;
497 if (c_time) {
498 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
500 if (a_time) {
501 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
503 if (m_time) {
504 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
506 if (w_time) {
507 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
509 if (mode) {
510 *mode = SVAL(rdata, 32);
512 if (size) {
513 *size = IVAL(rdata, 48);
515 if (ino) {
516 *ino = IVAL(rdata, 64);
519 if (rdata) free(rdata);
520 if (rparam) free(rparam);
521 return True;
525 /****************************************************************************
526 send a qfileinfo call
527 ****************************************************************************/
528 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
529 uint16 *mode, size_t *size,
530 time_t *c_time, time_t *a_time, time_t *m_time,
531 time_t *w_time, SMB_INO_T *ino)
533 int data_len = 0;
534 int param_len = 0;
535 uint16 setup = TRANSACT2_QFILEINFO;
536 pstring param;
537 char *rparam=NULL, *rdata=NULL;
539 /* if its a win95 server then fail this - win95 totally screws it
540 up */
541 if (cli->win95) return False;
543 param_len = 4;
545 memset(param, 0, param_len);
546 SSVAL(param, 0, fnum);
547 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
549 if (!cli_send_trans(cli, SMBtrans2,
550 NULL, /* name */
551 -1, 0, /* fid, flags */
552 &setup, 1, 0, /* setup, length, max */
553 param, param_len, 2, /* param, length, max */
554 NULL, data_len, cli->max_xmit /* data, length, max */
555 )) {
556 return False;
559 if (!cli_receive_trans(cli, SMBtrans2,
560 &rparam, &param_len,
561 &rdata, &data_len)) {
562 return False;
565 if (!rdata || data_len < 68) {
566 return False;
569 if (c_time) {
570 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
572 if (a_time) {
573 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
575 if (m_time) {
576 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
578 if (w_time) {
579 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
581 if (mode) {
582 *mode = SVAL(rdata, 32);
584 if (size) {
585 *size = IVAL(rdata, 48);
587 if (ino) {
588 *ino = IVAL(rdata, 64);
591 if (rdata) free(rdata);
592 if (rparam) free(rparam);
593 return True;