libsmb/ntlmssp_parse.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    simple kerberos5/SPNEGO routines
00004    Copyright (C) Andrew Tridgell 2001
00005    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
00006    Copyright (C) Andrew Bartlett 2002-2003
00007    
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012    
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017    
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 */
00022 
00023 #include "includes.h"
00024 
00025 /*
00026   this is a tiny msrpc packet generator. I am only using this to
00027   avoid tying this code to a particular varient of our rpc code. This
00028   generator is not general enough for all our rpc needs, its just
00029   enough for the spnego/ntlmssp code
00030 
00031   format specifiers are:
00032 
00033   U = unicode string (input is unix string)
00034   a = address (input is char *unix_string)
00035       (1 byte type, 1 byte length, unicode/ASCII string, all inline)
00036   A = ASCII string (input is unix string)
00037   B = data blob (pointer + length)
00038   b = data blob in header (pointer + length)
00039   D
00040   d = word (4 bytes)
00041   C = constant ascii string
00042  */
00043 BOOL msrpc_gen(DATA_BLOB *blob,
00044                const char *format, ...)
00045 {
00046         int i, n;
00047         va_list ap;
00048         char *s;
00049         uint8 *b;
00050         int head_size=0, data_size=0;
00051         int head_ofs, data_ofs;
00052 
00053         /* first scan the format to work out the header and body size */
00054         va_start(ap, format);
00055         for (i=0; format[i]; i++) {
00056                 switch (format[i]) {
00057                 case 'U':
00058                         s = va_arg(ap, char *);
00059                         head_size += 8;
00060                         data_size += str_charnum(s) * 2;
00061                         break;
00062                 case 'A':
00063                         s = va_arg(ap, char *);
00064                         head_size += 8;
00065                         data_size += str_ascii_charnum(s);
00066                         break;
00067                 case 'a':
00068                         n = va_arg(ap, int);
00069                         s = va_arg(ap, char *);
00070                         data_size += (str_charnum(s) * 2) + 4;
00071                         break;
00072                 case 'B':
00073                         b = va_arg(ap, uint8 *);
00074                         head_size += 8;
00075                         data_size += va_arg(ap, int);
00076                         break;
00077                 case 'b':
00078                         b = va_arg(ap, uint8 *);
00079                         head_size += va_arg(ap, int);
00080                         break;
00081                 case 'd':
00082                         n = va_arg(ap, int);
00083                         head_size += 4;
00084                         break;
00085                 case 'C':
00086                         s = va_arg(ap, char *);
00087                         head_size += str_charnum(s) + 1;
00088                         break;
00089                 }
00090         }
00091         va_end(ap);
00092 
00093         /* allocate the space, then scan the format again to fill in the values */
00094         *blob = data_blob(NULL, head_size + data_size);
00095 
00096         head_ofs = 0;
00097         data_ofs = head_size;
00098 
00099         va_start(ap, format);
00100         for (i=0; format[i]; i++) {
00101                 switch (format[i]) {
00102                 case 'U':
00103                         s = va_arg(ap, char *);
00104                         n = str_charnum(s);
00105                         SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
00106                         SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
00107                         SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
00108                         push_string(NULL, blob->data+data_ofs, s, n*2, STR_UNICODE|STR_NOALIGN);
00109                         data_ofs += n*2;
00110                         break;
00111                 case 'A':
00112                         s = va_arg(ap, char *);
00113                         n = str_ascii_charnum(s);
00114                         SSVAL(blob->data, head_ofs, n); head_ofs += 2;
00115                         SSVAL(blob->data, head_ofs, n); head_ofs += 2;
00116                         SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
00117                         push_string(NULL, blob->data+data_ofs, s, n, STR_ASCII|STR_NOALIGN);
00118                         data_ofs += n;
00119                         break;
00120                 case 'a':
00121                         n = va_arg(ap, int);
00122                         SSVAL(blob->data, data_ofs, n); data_ofs += 2;
00123                         s = va_arg(ap, char *);
00124                         n = str_charnum(s);
00125                         SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
00126                         if (0 < n) {
00127                                 push_string(NULL, blob->data+data_ofs, s, n*2,
00128                                             STR_UNICODE|STR_NOALIGN);
00129                         }
00130                         data_ofs += n*2;
00131                         break;
00132 
00133                 case 'B':
00134                         b = va_arg(ap, uint8 *);
00135                         n = va_arg(ap, int);
00136                         SSVAL(blob->data, head_ofs, n); head_ofs += 2;
00137                         SSVAL(blob->data, head_ofs, n); head_ofs += 2;
00138                         SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
00139                         if (n && b) /* don't follow null pointers... */
00140                                 memcpy(blob->data+data_ofs, b, n);
00141                         data_ofs += n;
00142                         break;
00143                 case 'd':
00144                         n = va_arg(ap, int);
00145                         SIVAL(blob->data, head_ofs, n); head_ofs += 4;
00146                         break;
00147                 case 'b':
00148                         b = va_arg(ap, uint8 *);
00149                         n = va_arg(ap, int);
00150                         memcpy(blob->data + head_ofs, b, n);
00151                         head_ofs += n;
00152                         break;
00153                 case 'C':
00154                         s = va_arg(ap, char *);
00155                         n = str_charnum(s) + 1;
00156                         head_ofs += push_string(NULL, blob->data+head_ofs, s, n,
00157                                                 STR_ASCII|STR_TERMINATE);
00158                         break;
00159                 }
00160         }
00161         va_end(ap);
00162 
00163         return True;
00164 }
00165 
00166 
00167 /* a helpful macro to avoid running over the end of our blob */
00168 #define NEED_DATA(amount) \
00169 if ((head_ofs + amount) > blob->length) { \
00170         return False; \
00171 }
00172 
00173 /*
00174   this is a tiny msrpc packet parser. This the the partner of msrpc_gen
00175 
00176   format specifiers are:
00177 
00178   U = unicode string (output is unix string)
00179   A = ascii string
00180   B = data blob
00181   b = data blob in header
00182   d = word (4 bytes)
00183   C = constant ascii string
00184  */
00185 
00186 BOOL msrpc_parse(const DATA_BLOB *blob,
00187                  const char *format, ...)
00188 {
00189         int i;
00190         va_list ap;
00191         char **ps, *s;
00192         DATA_BLOB *b;
00193         size_t head_ofs = 0;
00194         uint16 len1, len2;
00195         uint32 ptr;
00196         uint32 *v;
00197         pstring p;
00198 
00199         va_start(ap, format);
00200         for (i=0; format[i]; i++) {
00201                 switch (format[i]) {
00202                 case 'U':
00203                         NEED_DATA(8);
00204                         len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
00205                         len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
00206                         ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
00207 
00208                         ps = va_arg(ap, char **);
00209                         if (len1 == 0 && len2 == 0) {
00210                                 *ps = smb_xstrdup("");
00211                         } else {
00212                                 /* make sure its in the right format - be strict */
00213                                 if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) {
00214                                         return False;
00215                                 }
00216                                 if (len1 & 1) {
00217                                         /* if odd length and unicode */
00218                                         return False;
00219                                 }
00220                                 if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data)
00221                                         return False;
00222 
00223                                 if (0 < len1) {
00224                                         pull_string(NULL, p, blob->data + ptr, sizeof(p), 
00225                                                     len1, 
00226                                                     STR_UNICODE|STR_NOALIGN);
00227                                         (*ps) = smb_xstrdup(p);
00228                                 } else {
00229                                         (*ps) = smb_xstrdup("");
00230                                 }
00231                         }
00232                         break;
00233                 case 'A':
00234                         NEED_DATA(8);
00235                         len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
00236                         len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
00237                         ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
00238 
00239                         ps = va_arg(ap, char **);
00240                         /* make sure its in the right format - be strict */
00241                         if (len1 == 0 && len2 == 0) {
00242                                 *ps = smb_xstrdup("");
00243                         } else {
00244                                 if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) {
00245                                         return False;
00246                                 }
00247 
00248                                 if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data)
00249                                         return False;   
00250 
00251                                 if (0 < len1) {
00252                                         pull_string(NULL, p, blob->data + ptr, sizeof(p), 
00253                                                     len1, 
00254                                                     STR_ASCII|STR_NOALIGN);
00255                                         (*ps) = smb_xstrdup(p);
00256                                 } else {
00257                                         (*ps) = smb_xstrdup("");
00258                                 }
00259                         }
00260                         break;
00261                 case 'B':
00262                         NEED_DATA(8);
00263                         len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
00264                         len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
00265                         ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
00266 
00267                         b = (DATA_BLOB *)va_arg(ap, void *);
00268                         if (len1 == 0 && len2 == 0) {
00269                                 *b = data_blob(NULL, 0);
00270                         } else {
00271                                 /* make sure its in the right format - be strict */
00272                                 if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) {
00273                                         return False;
00274                                 }
00275 
00276                                 if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data)
00277                                         return False;   
00278                         
00279                                 *b = data_blob(blob->data + ptr, len1);
00280                         }
00281                         break;
00282                 case 'b':
00283                         b = (DATA_BLOB *)va_arg(ap, void *);
00284                         len1 = va_arg(ap, unsigned);
00285                         /* make sure its in the right format - be strict */
00286                         NEED_DATA(len1);
00287                         if (blob->data + head_ofs < (uint8 *)head_ofs || blob->data + head_ofs < blob->data)
00288                                 return False;   
00289                         
00290                         *b = data_blob(blob->data + head_ofs, len1);
00291                         head_ofs += len1;
00292                         break;
00293                 case 'd':
00294                         v = va_arg(ap, uint32 *);
00295                         NEED_DATA(4);
00296                         *v = IVAL(blob->data, head_ofs); head_ofs += 4;
00297                         break;
00298                 case 'C':
00299                         s = va_arg(ap, char *);
00300 
00301                         if (blob->data + head_ofs < (uint8 *)head_ofs || blob->data + head_ofs < blob->data)
00302                                 return False;   
00303         
00304                         head_ofs += pull_string(NULL, p, blob->data+head_ofs, sizeof(p), 
00305                                                 blob->length - head_ofs, 
00306                                                 STR_ASCII|STR_TERMINATE);
00307                         if (strcmp(s, p) != 0) {
00308                                 return False;
00309                         }
00310                         break;
00311                 }
00312         }
00313         va_end(ap);
00314 
00315         return True;
00316 }

Sambaに対してSat Aug 29 21:23:06 2009に生成されました。  doxygen 1.4.7