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