chiark / gitweb /
Fix C%d[%d] messages
[inn-innduct.git] / authprogs / smbval / smblib.c
1 /* UNIX SMBlib NetBIOS implementation
2
3    Version 1.0
4    SMBlib Routines
5
6    Copyright (C) Richard Sharpe 1996
7
8 */
9
10 /*
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "config.h"
27 #include "clibrary.h"
28 #include <ctype.h>
29 #include <signal.h>
30
31 int SMBlib_errno;
32 int SMBlib_SMB_Error;
33 #define SMBLIB_ERRNO
34 typedef unsigned char uchar;
35 #include "smblib-priv.h"
36
37 #include "rfcnb.h"
38
39 /* Initialize the SMBlib package     */
40
41 int SMB_Init()
42
43 {
44   signal(SIGPIPE, SIG_IGN);   /* Ignore these ... */
45
46   return 0;
47
48 }
49
50 int SMB_Term()
51
52 {
53
54   return 0;
55
56 }
57
58 /* SMB_Connect_Server: Connect to a server, but don't negotiate protocol */
59 /* or anything else ...                                                  */
60
61 SMB_Handle_Type SMB_Connect_Server(SMB_Handle_Type Con_Handle,
62                                    char *server, char *NTdomain)
63
64 { SMB_Handle_Type con;
65   char called[80], calling[80], *address;
66   int i;
67
68   /* Get a connection structure if one does not exist */
69
70   con = Con_Handle;
71
72   if (Con_Handle == NULL) {
73
74     if ((con = (struct SMB_Connect_Def *)malloc(sizeof(struct SMB_Connect_Def))) == NULL) {
75
76
77       SMBlib_errno = SMBlibE_NoSpace;
78       return NULL;
79     }
80
81   }
82
83   /* Init some things ... */
84
85   strlcpy(con->service, "", sizeof(con->service));
86   strlcpy(con->username, "", sizeof(con->username));
87   strlcpy(con->password, "", sizeof(con->password));
88   strlcpy(con->sock_options, "", sizeof(con->sock_options));
89   strlcpy(con->address, "", sizeof(con->address));
90   strlcpy(con->desthost, server, sizeof(con->desthost));
91   strlcpy(con->PDomain, NTdomain, sizeof(con->PDomain));
92   strlcpy(con->OSName, SMBLIB_DEFAULT_OSNAME, sizeof(con->OSName));
93   strlcpy(con->LMType, SMBLIB_DEFAULT_LMTYPE, sizeof(con->LMType));
94
95   SMB_Get_My_Name(con -> myname, sizeof(con -> myname));
96
97   con -> port = 0;                    /* No port selected */
98
99   /* Get some things we need for the SMB Header */
100
101   con -> pid = getpid();
102   con -> mid = con -> pid;      /* This will do for now ... */
103   con -> uid = 0;               /* Until we have done a logon, no uid ... */ 
104   con -> gid = getgid();
105
106   /* Now connect to the remote end, but first upper case the name of the
107      service we are going to call, sine some servers want it in uppercase */
108
109   for (i=0; i < strlen(server); i++)
110     called[i] = toupper(server[i]);
111                        
112   called[strlen(server)] = 0;    /* Make it a string */
113
114   for (i=0; i < strlen(con -> myname); i++)
115     calling[i] = toupper(con -> myname[i]);
116                        
117   calling[strlen(con -> myname)] = 0;    /* Make it a string */
118
119   if (strcmp(con -> address, "") == 0)
120     address = con -> desthost;
121   else
122     address = con -> address;
123
124   con -> Trans_Connect = RFCNB_Call(called,
125                                     calling,
126                                     address, /* Protocol specific */
127                                     con -> port);
128
129   /* Did we get one? */
130
131   if (con -> Trans_Connect == NULL) {
132
133     if (Con_Handle == NULL) {
134       Con_Handle = NULL;
135       free(con);
136     }
137     SMBlib_errno = -SMBlibE_CallFailed;
138     return NULL;
139
140   }
141
142   return(con);
143
144 }
145
146 /* Logon to the server. That is, do a session setup if we can. We do not do */
147 /* Unicode yet!                                                             */
148
149 int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName, 
150                      char *PassWord)
151
152 { struct RFCNB_Pkt *pkt;
153   int param_len, pkt_len, pass_len;
154   char *p, pword[128];
155
156   /* First we need a packet etc ... but we need to know what protocol has  */
157   /* been negotiated to figure out if we can do it and what SMB format to  */
158   /* use ...                                                               */
159
160   if (Con_Handle -> protocol < SMB_P_LanMan1) {
161
162     SMBlib_errno = SMBlibE_ProtLow;
163     return(SMBlibE_BAD);
164
165   }
166
167   strlcpy(pword, PassWord, sizeof(pword));
168   if (Con_Handle -> encrypt_passwords)
169   {
170     pass_len=24;
171     SMBencrypt((uchar *) PassWord, (uchar *)Con_Handle -> Encrypt_Key,(uchar *)pword); 
172   } 
173   else 
174         pass_len=strlen(pword);
175
176
177   /* Now build the correct structure */
178
179   if (Con_Handle -> protocol < SMB_P_NT1) {
180
181     param_len = strlen(UserName) + 1 + pass_len + 1 + 
182                 strlen(Con_Handle -> PDomain) + 1 + 
183                 strlen(Con_Handle -> OSName) + 1;
184
185     pkt_len = SMB_ssetpLM_len + param_len;
186
187     pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
188
189     if (pkt == NULL) {
190
191       SMBlib_errno = SMBlibE_NoSpace;
192       return(SMBlibE_BAD); /* Should handle the error */
193
194     }
195
196     memset(SMB_Hdr(pkt), 0, SMB_ssetpLM_len);
197     SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF);  /* Plunk in IDF */
198     *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
199     SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
200     SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
201     SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
202     SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
203     *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10;
204     *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF;    /* No extra command */
205     SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
206
207     SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT);
208     SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2);
209     SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid);
210     SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0);
211     SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, pass_len + 1);
212     SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0);
213     SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len);
214
215     /* Now copy the param strings in with the right stuff */
216
217     p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset);
218
219     /* Copy  in password, then the rest. Password has a null at end */
220
221     memcpy(p, pword, pass_len);
222
223     p = p + pass_len + 1;
224
225     strcpy(p, UserName);
226     p = p + strlen(UserName);
227     *p = 0;
228
229     p = p + 1;
230
231     strcpy(p, Con_Handle -> PDomain);
232     p = p + strlen(Con_Handle -> PDomain);
233     *p = 0;
234     p = p + 1;
235
236     strcpy(p, Con_Handle -> OSName);
237     p = p + strlen(Con_Handle -> OSName);
238     *p = 0;
239
240   }
241   else {
242
243     /* We don't admit to UNICODE support ... */
244
245     param_len = strlen(UserName) + 1 + pass_len + 
246                 strlen(Con_Handle -> PDomain) + 1 + 
247                 strlen(Con_Handle -> OSName) + 1 +
248                 strlen(Con_Handle -> LMType) + 1;
249
250     pkt_len = SMB_ssetpNTLM_len + param_len;
251
252     pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
253
254     if (pkt == NULL) {
255
256       SMBlib_errno = SMBlibE_NoSpace;
257       return(-1); /* Should handle the error */
258
259     }
260
261     memset(SMB_Hdr(pkt), 0, SMB_ssetpNTLM_len);
262     SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF);  /* Plunk in IDF */
263     *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
264     SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
265     SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
266     SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
267     SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
268     *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13;
269     *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF;    /* No extra command */
270     SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
271
272     SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT);
273     SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 0);
274     SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0);
275     SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0);
276     SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, pass_len);
277     SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0);
278     SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0);
279     SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0);
280     SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len);
281
282     /* Now copy the param strings in with the right stuff */
283
284     p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset);
285
286     /* Copy  in password, then the rest. Password has no null at end */
287
288     memcpy(p, pword, pass_len);
289
290     p = p + pass_len;
291
292     strcpy(p, UserName);
293     p = p + strlen(UserName);
294     *p = 0;
295
296     p = p + 1;
297
298     strcpy(p, Con_Handle -> PDomain);
299     p = p + strlen(Con_Handle -> PDomain);
300   *p = 0;
301     p = p + 1;
302
303     strcpy(p, Con_Handle -> OSName);
304     p = p + strlen(Con_Handle -> OSName);
305     *p = 0;
306     p = p + 1;
307
308     strcpy(p, Con_Handle -> LMType);
309     p = p + strlen(Con_Handle -> LMType);
310     *p = 0;
311
312   }
313
314   /* Now send it and get a response */
315
316   if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0){
317
318     RFCNB_Free_Pkt(pkt);
319     SMBlib_errno = SMBlibE_SendFailed;
320     return(SMBlibE_BAD);
321
322   }
323
324   /* Now get the response ... */
325
326   if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
327
328     RFCNB_Free_Pkt(pkt);
329     SMBlib_errno = SMBlibE_RecvFailed;
330     return(SMBlibE_BAD);
331
332   }
333
334   /* Check out the response type ... */
335
336   if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) {  /* Process error */
337
338     SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
339     RFCNB_Free_Pkt(pkt);
340     SMBlib_errno = SMBlibE_Remote;
341     return(SMBlibE_BAD);
342
343   }
344 /** @@@ mdz: check for guest login { **/
345        if (SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset) & 0x1)
346        {
347                /* do we allow guest login? NO! */
348                return(SMBlibE_BAD);
349  
350        }
351  /** @@@ mdz: } **/
352
353
354   /* Now pick up the UID for future reference ... */
355
356   Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset);
357   RFCNB_Free_Pkt(pkt);
358
359   return(0);
360
361 }
362
363
364 /* Disconnect from the server, and disconnect all tree connects */
365
366 int SMB_Discon(SMB_Handle_Type Con_Handle, bool KeepHandle)
367
368 {
369
370   /* We just disconnect the connection for now ... */
371
372   RFCNB_Hangup(Con_Handle -> Trans_Connect);
373
374   if (!KeepHandle)
375     free(Con_Handle);
376
377   return(0);
378
379 }