2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* UNIX SMBlib NetBIOS implementation
14 Copyright (C) Richard Sharpe 1996
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation; either version 2 of the License, or
21 (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 #include "rfcnb/rfcnb.h"
35 #include "smblib/smblib-priv.h"
41 SMB_Tree_Handle SMBapi_Tree
= NULL
;
43 /* Send an api request to the \\server\IPC$ tree, with a \PIPE\LANMAN api */
44 /* request to change the user's password */
46 #define SMB_LMAPI_SLOT "\\PIPE\\LANMAN"
47 #define SMB_LMAPI_SUPW_DESC "zb16b16WW"
49 int SMBapi_NetUserPasswordSet(SMB_Tree_Handle tree
, char *user
,
50 char *oldpass
, char *newpass
, int *apiStatus
)
53 struct RFCNB_Pkt
*pkt
;
54 int param_len
, i
, pkt_len
, pad_api_name
= FALSE
;
57 /* Get a packet, we need one with space for a transact plus. The calc */
58 /* below lays it all out as it is, including the empty string after the */
59 /* descriptor and before the username */
61 param_len
= 2 + strlen(SMB_LMAPI_SUPW_DESC
) + 1 +
62 1 /* for empty string :-) */ + strlen(user
) +
65 /* We have no setup words, wo we don't account for them */
67 pkt_len
= SMB_trans_len
+ 2 /* for bcc */ + strlen(SMB_LMAPI_SLOT
) + 1;
69 /* Pad things onto a word boundary ... */
71 if (pkt_len
& 0x0001) {
72 pkt_len
= pkt_len
+ 1;
76 pkt_len
= pkt_len
+ param_len
;
78 /* Now allocate space for the packet, build it and send it */
80 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
84 SMBlib_errno
= SMBlibE_NoSpace
;
85 return(SMBlibE_BAD
); /* Should handle the error */
89 memset(SMB_Hdr(pkt
), 0, SMB_trans_len
);
90 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
91 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBtrans
;
92 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
93 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
94 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
95 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
96 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 14;
98 SSVAL(SMB_Hdr(pkt
), SMB_trans_tpc_offset
, param_len
);
99 SSVAL(SMB_Hdr(pkt
), SMB_trans_tdc_offset
, 0);
100 SSVAL(SMB_Hdr(pkt
), SMB_trans_mpc_offset
, 4);
101 SSVAL(SMB_Hdr(pkt
), SMB_trans_mdc_offset
, 0);
102 SSVAL(SMB_Hdr(pkt
), SMB_trans_msc_offset
, 0);
103 SSVAL(SMB_Hdr(pkt
), SMB_trans_flg_offset
, 0);
104 SIVAL(SMB_Hdr(pkt
), SMB_trans_tmo_offset
, 5000);
105 SSVAL(SMB_Hdr(pkt
), SMB_trans_pbc_offset
, param_len
);
106 SSVAL(SMB_Hdr(pkt
), SMB_trans_pbo_offset
, SMB_trans_len
+ 2 +
107 strlen(SMB_LMAPI_SLOT
) + 1);
108 SSVAL(SMB_Hdr(pkt
), SMB_trans_dbc_offset
, 0);
109 SSVAL(SMB_Hdr(pkt
), SMB_trans_dbo_offset
, 0);
111 /* Now put in the bcc and the rest of the info ... */
113 SSVAL(SMB_Hdr(pkt
), SMB_trans_len
, param_len
+ strlen(SMB_LMAPI_SLOT
) + 1);
115 p
= SMB_Hdr(pkt
) + SMB_trans_len
+ 2; /* Skip the BCC and ect */
117 strcpy(p
, SMB_LMAPI_SLOT
);
118 p
= p
+ strlen(SMB_LMAPI_SLOT
) + 1;
120 if (pad_api_name
== TRUE
) /* Pad if we need to */
123 /* SSVAL(p, 0, 65000); /* Check the result */
124 SSVAL(p
, 0, SMB_LMapi_UserPasswordSet
); /* The api call */
128 strcpy(p
, SMB_LMAPI_SUPW_DESC
); /* Copy in the param desc */
130 p
= p
+ strlen(SMB_LMAPI_SUPW_DESC
) + 1;
132 *p
= 0; /* Stick in that null string */
137 p
= p
+ strlen(user
) + 1;
139 strncpy(p
, oldpass
, 16);
143 strncpy(p
, newpass
, 16);
147 SSVAL(p
, 0, 0); /* Seems to be zero always? */
148 SSVAL(p
, 2, strlen(newpass
)); /* Length of new password ...*/
150 /* Now send the lot and get a response ... */
152 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
155 fprintf(stderr
, "Error sending Trans request\n");
159 SMBlib_errno
= SMBlibE_SendFailed
;
164 /* Now get the response ... */
166 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
169 fprintf(stderr
, "Error receiving response to Trans request\n");
173 SMBlib_errno
= SMBlibE_RecvFailed
;
178 /* Check out the response type ... */
180 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
183 fprintf(stderr
, "SMB_trans failed with errorclass = %i, Error Code = %i\n",
184 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
185 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
188 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
190 SMBlib_errno
= SMBlibE_Remote
;
195 /* All ok, pass back the status */
197 *apiStatus
= SVAL(SMB_Hdr(pkt
), SVAL(SMB_Hdr(pkt
), SMB_transr_pbo_offset
));
204 #define SMB_LMAPI_SUI_DESC "zWsTPWW"
205 #define SMB_LMAPI_SUI_DATA_DESC "B16"
207 /* Set user info ... specifically, password */
209 int SMBapi_NetSetUserInfo(SMB_Tree_Handle tree
, char *user
,
210 char *newpass
, int *apiStatus
)
213 struct RFCNB_Pkt
*pkt
;
214 int param_len
, i
, pkt_len
, data_len
, pad_api_name
= FALSE
;
215 int pad_params
= FALSE
;
218 /* Get a packet, we need one with space for a transact plus. The calc */
219 /* below lays it all out as it is, including the empty string after the */
220 /* descriptor and before the username */
222 param_len
= 2 + strlen(SMB_LMAPI_SUI_DESC
) + 1 +
223 + strlen(SMB_LMAPI_SUI_DATA_DESC
) + 1 + strlen(user
) +
228 /* We have no setup words, so we don't account for them */
230 pkt_len
= SMB_trans_len
+ 2 /* for bcc */ + strlen(SMB_LMAPI_SLOT
) + 1;
232 if (pkt_len
& 0x0001) { /* Pad to a WORD boundary */
238 if (param_len
& 0x0001) { /* pad to a WORD boundary */
244 pkt_len
= pkt_len
+ param_len
+ data_len
;
246 if (pad_api_name
== TRUE
) pkt_len
= pkt_len
+ 1;
247 if (pad_params
== TRUE
) pkt_len
= pkt_len
+ 1;
249 /* Now allocate space for the packet, build it and send it */
251 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
255 SMBlib_errno
= SMBlibE_NoSpace
;
256 return(SMBlibE_BAD
); /* Should handle the error */
260 memset(SMB_Hdr(pkt
), 0, SMB_trans_len
);
261 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
262 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBtrans
;
263 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, tree
-> con
-> pid
);
264 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, tree
-> tid
);
265 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, tree
-> con
-> mid
);
266 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, tree
-> con
-> uid
);
267 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 14;
269 SSVAL(SMB_Hdr(pkt
), SMB_trans_tpc_offset
, param_len
);
270 SSVAL(SMB_Hdr(pkt
), SMB_trans_tdc_offset
, data_len
);
271 SSVAL(SMB_Hdr(pkt
), SMB_trans_mpc_offset
, 4);
272 SSVAL(SMB_Hdr(pkt
), SMB_trans_mdc_offset
, 0);
273 SSVAL(SMB_Hdr(pkt
), SMB_trans_msc_offset
, 0);
274 SSVAL(SMB_Hdr(pkt
), SMB_trans_flg_offset
, 0);
275 SIVAL(SMB_Hdr(pkt
), SMB_trans_tmo_offset
, 5000);
276 SSVAL(SMB_Hdr(pkt
), SMB_trans_pbc_offset
, param_len
);
277 SSVAL(SMB_Hdr(pkt
), SMB_trans_pbo_offset
, SMB_trans_len
+ 2 +
278 strlen(SMB_LMAPI_SLOT
) + 1);
279 SSVAL(SMB_Hdr(pkt
), SMB_trans_dbc_offset
, data_len
);
280 SSVAL(SMB_Hdr(pkt
), SMB_trans_dbo_offset
, pkt_len
- data_len
);
282 /* Now put in the bcc and the rest of the info ... */
284 SSVAL(SMB_Hdr(pkt
), SMB_trans_len
, param_len
+ strlen(SMB_LMAPI_SLOT
) +
287 p
= SMB_Hdr(pkt
) + SMB_trans_len
+ 2; /* Skip the BCC and ect */
289 strcpy(p
, SMB_LMAPI_SLOT
);
290 p
= p
+ strlen(SMB_LMAPI_SLOT
) + 1;
292 if (pad_api_name
== TRUE
) /* Pad to a word boundary */
295 /* SSVAL(p, 0, 65000); /* Check the result */
296 SSVAL(p
, 0, SMB_LMapi_SetUserInfo
); /* The api call */
300 strcpy(p
, SMB_LMAPI_SUI_DESC
); /* Copy in the param desc */
302 p
= p
+ strlen(SMB_LMAPI_SUI_DESC
) + 1;
304 strcpy(p
, SMB_LMAPI_SUI_DATA_DESC
); /* Copy in second descriptor */
306 p
= p
+ strlen(SMB_LMAPI_SUI_DATA_DESC
) + 1;
310 p
= p
+ strlen(user
) + 1;
312 SSVAL(p
, 0, 1); /* Claim that we have a level 1 struct ? */
316 SSVAL(p
, 0, 3); /* Set the password */
317 SSVAL(p
, 2, 1); /* Seems to be one ... */
318 SSVAL(p
, 4, strlen(newpass
)); /* Length of new password ...*/
320 /* Now copy the data in ... */
324 if (pad_params
== TRUE
)
329 /* Now send the lot and get a response ... */
331 if (RFCNB_Send(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
334 fprintf(stderr
, "Error sending Trans SetUserInfo request\n");
338 SMBlib_errno
= SMBlibE_SendFailed
;
343 /* Now get the response ... */
345 if (RFCNB_Recv(tree
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
348 fprintf(stderr
, "Error receiving response to Trans SetUserInfo request\n");
352 SMBlib_errno
= SMBlibE_RecvFailed
;
357 /* Check out the response type ... */
359 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
362 fprintf(stderr
, "SMB_trans SetUserInfo failed with errorclass = %i, Error Code = %i\n",
363 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
364 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
367 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
369 SMBlib_errno
= SMBlibE_Remote
;
374 /* All ok, pass back the status */
376 *apiStatus
= SVAL(SMB_Hdr(pkt
), SVAL(SMB_Hdr(pkt
), SMB_transr_pbo_offset
));
383 /* List all the shares available on a server */
385 int SMBapi_NetShareEnum(SMB_Tree_Handle tree
, char *enum_buf
, int bufsiz
,
386 int *shares_returned
, int *shares_total
)