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