1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31
32 #pragma ident "%Z%%M% %I% %E% SMI"
33
34 /*
35 * lssmb.c: Contains all code specific to the MS-NET file server.
36 * Undef SMBSERVER to remove SMB support.
37 */
38
39
40 #include <stdio.h>
41 #include <string.h>
42 #include <sys/param.h>
43 #include <sys/tiuser.h>
44
45 #include "lsparam.h"
46 #include "lssmbmsg.h"
47 #include "lsdbf.h"
48
49
50 #ifdef SMBSERVER
51
52
53 /*
54 * Dlevel - Debug level for DEBUG((level, ... ) type calls
55 * Msnet - Who is logging this message (the SMB code is)
56 */
57
58 #define Dlevel 3
59 #define Msnet "SMB parser:"
60
61 extern char *malloc();
62 char *bytes_to_ascii();
63 void getword(char *addr, short *w);
64
65 /*
66 * In the event of an error, it may be necessary to send a response to
67 * the remote node before closing the virtual circuit. The following
68 * is the return message that should be sent. (Initially, I am not
69 * bothering to send the response message; I am assuming that the
70 * MS-NET client will be able to figure out that things went wrong, but
71 * we may find that is not the case.
72 */
73
74 static unsigned char errbuf[] = {
75 /* NegProt Return */ 0xff, 'S', 'M', 'B', 0x72,
76 /* ERRSRV */ 0x2,
77 0,
78 /* SMBerror */ 0x1, 0,
79 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81 0, 0,
82 0, 0,
83 0, 0, 0, 0,
84 /* wcnt == 1 */ 1,
85 /* no dialects */ 0xff, 0xff,
86 0, 0
87 };
88
89
90 /*
91 * s m b s e r v i c e
92 *
93 * Function called by listener process when it receives a connect
94 * request from a node that wants to talk Microsoft's MS-NET Core
95 * Protocol...the functions gets called after the listener forks.
96 */
97
98 void
smbservice(bp,bufsize,argv)99 smbservice(bp, bufsize, argv)
100 char *bp; /* pointer to message buffer */
101 int bufsize; /* size of message */
102 char **argv; /* server arguments */
103 {
104 char *server = *argv; /* path of server */
105 char logbuf[256];
106 char **args;
107 int i, m_size;
108 int twos, nulls;
109 char *p, *q;
110 short size;
111
112 /*
113 * Is this really a correct negotiate protocol message?
114 */
115
116 if (*(bp+FSP_COM) != FSPnegprot){
117 sprintf(logbuf, "%s: Bad Command Code, 0x%x",
118 Msnet, *(bp+FSP_COM));
119 goto badexit;
120 }
121
122 /*
123 * Are there exactly 0 argument words in the message?
124 */
125
126 if (*(bp+FSP_WCNT) != 0){
127 sprintf(logbuf, "%s: Incorrect # of Parameter Words, 0x%x",
128 Msnet, *(bp+FSP_WCNT));
129 goto badexit;
130 }
131
132 /*
133 * get the size of the data in the message
134 */
135
136 p = bp + FSP_PARMS;
137 getword(p, &size);
138
139 /*
140 * make sure the data is valid; it should have a series of
141 * "dialect" strings, which are of the form [02 string 00].
142 * if(twos == nulls) then the data is well formed, else something
143 * is wrong.
144 */
145
146 twos = nulls = 0;
147 p += 2;
148 for(q = p; q < p + size; ++q){
149 if(*q == '\0')
150 nulls++;
151 else if(*q == 02)
152 twos++;
153 }
154
155 if(twos != nulls){
156 sprintf(logbuf, "%s: Bad Data Format, twos=%d, nulls=%d",
157 Msnet, twos, nulls);
158 goto badexit;
159 }
160
161 /*
162 * Count the number of arguments that were passed
163 * to me by the listener...
164 */
165
166 for(i=0, args=argv; *args; ++args, ++i)
167 ;
168
169 /*
170 * There are a few kinds of arguments that I will pass to the server:
171 *
172 * -D<string> - means "the client speaks this dialect . . ."
173 * there me be more than one of these, if the client
174 * is able to speak multiple dialects.
175 *
176 * Any arguments passed to me by the listener will be passed along
177 * as is . . .
178 *
179 * Allocate an array of "char *"s that will let me point to all
180 * of the following:
181 * 1. As many -D options as are needed (the exact number is
182 * contained in the variable "twos"),
183 * 2. One -A option for the single logical name
184 * of the client,
185 * 3. As many positions as are needed to pass along the arguments
186 * passed to me by the listener (variable "i"),
187 * 4. The name of the Server executable file (always arg[0]), and
188 * 5. "Ascii-ized" version of input message as last arg.
189 * 6. A NULL terminator.
190 */
191
192 m_size = sizeof(char *) * (twos + i + 4);
193 if((args = (char **)malloc((unsigned)m_size)) == 0){
194 sprintf(logbuf, "%s: Can't malloc arg space, %d bytes",
195 Msnet, m_size);
196 goto badexit;
197 }
198
199 /*
200 * put together the first argument to exec(2) which should be
201 * the full pathname of the executable server file.
202 */
203
204 args[0] = server;
205
206 /*
207 * Send dialect strings down, in order of preference
208 */
209
210 for(i=1, q=p; q < p + size; ++i, ++q){
211 q = strchr(q, 02); /* find start of string */
212
213 m_size = strlen(++q) + 1 + 2;
214 if((args[i] = malloc((unsigned)m_size)) == 0){
215 sprintf(logbuf,
216 "%s: Can't malloc Server Path buf, %d bytes",
217 Msnet, m_size);
218 goto badexit;
219 }
220
221 strcpy(args[i], "-D");
222 strcat(args[i], q); /* put -Ddialect\0 in arglist */
223 q = strchr(q, '\0'); /* find end of string */
224 }
225
226 /*
227 * Add in arguments that were passed to me by the listener
228 * first arg is server path, so we ignore that.
229 */
230
231 for( ++argv; *argv; ++argv, ++i)
232 args[i] = *argv;
233
234 /*
235 * add ascii-ized version of message
236 */
237
238 args[i++] = bytes_to_ascii(bp, bufsize);
239
240 /*
241 * NULL terminate the list
242 */
243
244 args[i] = NULL;
245
246 exec_cmd((dbf_t *)0, args);
247 return; /* error logged in start_server */
248
249 badexit:
250 logmessage(logbuf);
251 }
252
253
254 /*
255 * g e t w o r d
256 *
257 * move a word from an arbitrary position in a character buffer, into
258 * a short, and flip the bytes.
259 * (NOTE that word is a 16-bit iapx-286 word).
260 */
261
262 void
getword(char * addr,short * w)263 getword(char *addr, short *w)
264 {
265 lobyte(*w) = *addr++;
266 hibyte(*w) = *addr;
267 }
268
269 /* b y t e s _ t o _ a s c i i
270 * Routine to convert a binary array to a printable sequence of
271 * characters. For example, if the input to this routine were:
272 *
273 * inbuf = "012", and n = 3
274 *
275 * then the output would be a pointer to the string:
276 *
277 * "303132"
278 *
279 * No assumption is made about NULL terminators on input, because
280 * it is probably binary, and not a string.
281 */
282
283
284 char *
bytes_to_ascii(inbuf,n)285 bytes_to_ascii(inbuf, n)
286 char *inbuf; /* initialized buffer of binary data */
287 int n; /* size of input buffer */
288 {
289 char *outbuf; /* return string */
290 char *p; /* scratch pointer */
291 int i; /* scratch variable */
292
293 /* malloc 2x space for output plus one for NULL */
294 if (outbuf = malloc(n * 2 + 1)) {
295 /* Fill in output buffer, with 2 character, capitalized hex. */
296 for (i = 0, p = outbuf; i < n; ++inbuf, p += 2, ++i) {
297 sprintf(p, "%2.2X", *inbuf);
298 }
299 return(outbuf);
300 }
301 else
302 return(NULL);
303 }
304
305
306
307 #else
308
309 void
smbservice(bp,size,argv)310 smbservice(bp, size, argv)
311 char *bp; /* pointer to message buffer */
312 int size; /* size of message */
313 char **argv; /* server arguments */
314 {
315 logmessage("SMB service NOT supported");
316 }
317
318 #endif /* SMBSERVICE */
319