]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/smblib/smblib-api.c
Source Format Enforcement (#1234)
[thirdparty/squid.git] / lib / smblib / smblib-api.c
1 /*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
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.
7 */
8
9 /* UNIX SMBlib NetBIOS implementation
10
11 Version 1.0
12 SMB API Calls ...
13
14 Copyright (C) Richard Sharpe 1996
15 */
16
17 /*
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.
22
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.
27
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.
31 */
32
33 #include "squid.h"
34 #include "rfcnb/rfcnb.h"
35 #include "smblib/smblib-priv.h"
36
37 #if HAVE_STRING_H
38 #include <string.h>
39 #endif
40
41 SMB_Tree_Handle SMBapi_Tree = NULL;
42
43 /* Send an api request to the \\server\IPC$ tree, with a \PIPE\LANMAN api */
44 /* request to change the user's password */
45
46 #define SMB_LMAPI_SLOT "\\PIPE\\LANMAN"
47 #define SMB_LMAPI_SUPW_DESC "zb16b16WW"
48
49 int SMBapi_NetUserPasswordSet(SMB_Tree_Handle tree, char *user,
50 char *oldpass, char *newpass, int *apiStatus)
51
52 {
53 struct RFCNB_Pkt *pkt;
54 int param_len, i, pkt_len, pad_api_name = FALSE;
55 char *p;
56
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 */
60
61 param_len = 2 + strlen(SMB_LMAPI_SUPW_DESC) + 1 +
62 1 /* for empty string :-) */ + strlen(user) +
63 1 + 16 + 16 + 2 + 2;
64
65 /* We have no setup words, wo we don't account for them */
66
67 pkt_len = SMB_trans_len + 2 /* for bcc */ + strlen(SMB_LMAPI_SLOT) + 1;
68
69 /* Pad things onto a word boundary ... */
70
71 if (pkt_len & 0x0001) {
72 pkt_len = pkt_len + 1;
73 pad_api_name = TRUE;
74 }
75
76 pkt_len = pkt_len + param_len;
77
78 /* Now allocate space for the packet, build it and send it */
79
80 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
81
82 if (pkt == NULL) {
83
84 SMBlib_errno = SMBlibE_NoSpace;
85 return(SMBlibE_BAD); /* Should handle the error */
86
87 }
88
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;
97
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);
110
111 /* Now put in the bcc and the rest of the info ... */
112
113 SSVAL(SMB_Hdr(pkt), SMB_trans_len, param_len + strlen(SMB_LMAPI_SLOT) + 1);
114
115 p = SMB_Hdr(pkt) + SMB_trans_len + 2; /* Skip the BCC and etc */
116
117 strcpy(p, SMB_LMAPI_SLOT);
118 p = p + strlen(SMB_LMAPI_SLOT) + 1;
119
120 if (pad_api_name == TRUE) /* Pad if we need to */
121 p = p + 1;
122
123 /* SSVAL(p, 0, 65000); /* Check the result */
124 SSVAL(p, 0, SMB_LMapi_UserPasswordSet); /* The api call */
125
126 p = p + 2;
127
128 strcpy(p, SMB_LMAPI_SUPW_DESC); /* Copy in the param desc */
129
130 p = p + strlen(SMB_LMAPI_SUPW_DESC) + 1;
131
132 *p = 0; /* Stick in that null string */
133 p = p + 1;
134
135 strcpy(p, user);
136
137 p = p + strlen(user) + 1;
138
139 strncpy(p, oldpass, 16);
140
141 p = p + 16;
142
143 strncpy(p, newpass, 16);
144
145 p = p + 16;
146
147 SSVAL(p, 0, 0); /* Seems to be zero always? */
148 SSVAL(p, 2, strlen(newpass)); /* Length of new password ...*/
149
150 /* Now send the lot and get a response ... */
151
152 if (RFCNB_Send(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) {
153
154 #ifdef DEBUG
155 fprintf(stderr, "Error sending Trans request\n");
156 #endif
157
158 RFCNB_Free_Pkt(pkt);
159 SMBlib_errno = SMBlibE_SendFailed;
160 return(SMBlibE_BAD);
161
162 }
163
164 /* Now get the response ... */
165
166 if (RFCNB_Recv(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) {
167
168 #ifdef DEBUG
169 fprintf(stderr, "Error receiving response to Trans request\n");
170 #endif
171
172 RFCNB_Free_Pkt(pkt);
173 SMBlib_errno = SMBlibE_RecvFailed;
174 return(SMBlibE_BAD);
175
176 }
177
178 /* Check out the response type ... */
179
180 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
181
182 #ifdef DEBUG
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));
186 #endif
187
188 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
189 RFCNB_Free_Pkt(pkt);
190 SMBlib_errno = SMBlibE_Remote;
191 return(SMBlibE_BAD);
192
193 }
194
195 /* All ok, pass back the status */
196
197 *apiStatus = SVAL(SMB_Hdr(pkt), SVAL(SMB_Hdr(pkt), SMB_transr_pbo_offset));
198 RFCNB_Free_Pkt(pkt);
199
200 return(0);
201
202 }
203
204 #define SMB_LMAPI_SUI_DESC "zWsTPWW"
205 #define SMB_LMAPI_SUI_DATA_DESC "B16"
206
207 /* Set user info ... specifically, password */
208
209 int SMBapi_NetSetUserInfo(SMB_Tree_Handle tree, char *user,
210 char *newpass, int *apiStatus)
211
212 {
213 struct RFCNB_Pkt *pkt;
214 int param_len, i, pkt_len, data_len, pad_api_name = FALSE;
215 int pad_params = FALSE;
216 char *p;
217
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 */
221
222 param_len = 2 + strlen(SMB_LMAPI_SUI_DESC) + 1 +
223 + strlen(SMB_LMAPI_SUI_DATA_DESC) + 1 + strlen(user) +
224 1 + 2 + 2 + 2 + 2;
225
226 data_len = 16;
227
228 /* We have no setup words, so we don't account for them */
229
230 pkt_len = SMB_trans_len + 2 /* for bcc */ + strlen(SMB_LMAPI_SLOT) + 1;
231
232 if (pkt_len & 0x0001) { /* Pad to a WORD boundary */
233
234 pad_api_name = TRUE;
235
236 }
237
238 if (param_len & 0x0001) { /* pad to a WORD boundary */
239
240 pad_params = TRUE;
241
242 }
243
244 pkt_len = pkt_len + param_len + data_len;
245
246 if (pad_api_name == TRUE) pkt_len = pkt_len + 1;
247 if (pad_params == TRUE) pkt_len = pkt_len + 1;
248
249 /* Now allocate space for the packet, build it and send it */
250
251 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
252
253 if (pkt == NULL) {
254
255 SMBlib_errno = SMBlibE_NoSpace;
256 return(SMBlibE_BAD); /* Should handle the error */
257
258 }
259
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;
268
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);
281
282 /* Now put in the bcc and the rest of the info ... */
283
284 SSVAL(SMB_Hdr(pkt), SMB_trans_len, param_len + strlen(SMB_LMAPI_SLOT) +
285 1 + data_len);
286
287 p = SMB_Hdr(pkt) + SMB_trans_len + 2; /* Skip the BCC and etc */
288
289 strcpy(p, SMB_LMAPI_SLOT);
290 p = p + strlen(SMB_LMAPI_SLOT) + 1;
291
292 if (pad_api_name == TRUE) /* Pad to a word boundary */
293 p = p + 1;
294
295 /* SSVAL(p, 0, 65000); */ /* Check the result */
296 SSVAL(p, 0, SMB_LMapi_SetUserInfo); /* The api call */
297
298 p = p + 2;
299
300 strcpy(p, SMB_LMAPI_SUI_DESC); /* Copy in the param desc */
301
302 p = p + strlen(SMB_LMAPI_SUI_DESC) + 1;
303
304 strcpy(p, SMB_LMAPI_SUI_DATA_DESC); /* Copy in second descriptor */
305
306 p = p + strlen(SMB_LMAPI_SUI_DATA_DESC) + 1;
307
308 strcpy(p, user);
309
310 p = p + strlen(user) + 1;
311
312 SSVAL(p, 0, 1); /* Claim that we have a level 1 struct ? */
313
314 p = p + 2;
315
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 ...*/
319
320 /* Now copy the data in ... */
321
322 p = p + 6;
323
324 if (pad_params == TRUE)
325 p = p + 1;
326
327 strcpy(p, newpass);
328
329 /* Now send the lot and get a response ... */
330
331 if (RFCNB_Send(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) {
332
333 #ifdef DEBUG
334 fprintf(stderr, "Error sending Trans SetUserInfo request\n");
335 #endif
336
337 RFCNB_Free_Pkt(pkt);
338 SMBlib_errno = SMBlibE_SendFailed;
339 return(SMBlibE_BAD);
340
341 }
342
343 /* Now get the response ... */
344
345 if (RFCNB_Recv(tree -> con -> Trans_Connect, pkt, pkt_len) < 0) {
346
347 #ifdef DEBUG
348 fprintf(stderr, "Error receiving response to Trans SetUserInfo request\n");
349 #endif
350
351 RFCNB_Free_Pkt(pkt);
352 SMBlib_errno = SMBlibE_RecvFailed;
353 return(SMBlibE_BAD);
354
355 }
356
357 /* Check out the response type ... */
358
359 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
360
361 #ifdef DEBUG
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));
365 #endif
366
367 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
368 RFCNB_Free_Pkt(pkt);
369 SMBlib_errno = SMBlibE_Remote;
370 return(SMBlibE_BAD);
371
372 }
373
374 /* All ok, pass back the status */
375
376 *apiStatus = SVAL(SMB_Hdr(pkt), SVAL(SMB_Hdr(pkt), SMB_transr_pbo_offset));
377 RFCNB_Free_Pkt(pkt);
378
379 return(0);
380
381 }
382
383 /* List all the shares available on a server */
384
385 int SMBapi_NetShareEnum(SMB_Tree_Handle tree, char *enum_buf, int bufsiz,
386 int *shares_returned, int *shares_total)
387
388 {
389
390 }
391