2 Unix SMB/CIFS implementation.
3 simple kerberos5/SPNEGO routines
4 Copyright (C) Andrew Tridgell 2001
5 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
6 Copyright (C) Andrew Bartlett 2002-2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 this is a tiny msrpc packet generator. I am only using this to
27 avoid tying this code to a particular varient of our rpc code. This
28 generator is not general enough for all our rpc needs, its just
29 enough for the spnego/ntlmssp code
31 format specifiers are:
33 U = unicode string (input is unix string)
34 a = address (input is BOOL unicode, char *unix_string)
35 (1 byte type, 1 byte length, unicode/ASCII string, all inline)
36 A = ASCII string (input is unix string)
37 B = data blob (pointer + length)
38 b = data blob in header (pointer + length)
41 C = constant ascii string
43 BOOL
msrpc_gen(DATA_BLOB
*blob
,
44 const char *format
, ...)
50 int head_size
=0, data_size
=0;
51 int head_ofs
, data_ofs
;
54 /* first scan the format to work out the header and body size */
56 for (i
=0; format
[i
]; i
++) {
59 s
= va_arg(ap
, char *);
61 data_size
+= str_charnum(s
) * 2;
64 s
= va_arg(ap
, char *);
66 data_size
+= str_ascii_charnum(s
);
69 unicode
= va_arg(ap
, BOOL
);
71 s
= va_arg(ap
, char *);
73 data_size
+= (str_charnum(s
) * 2) + 4;
75 data_size
+= (str_ascii_charnum(s
)) + 4;
79 b
= va_arg(ap
, uint8
*);
81 data_size
+= va_arg(ap
, int);
84 b
= va_arg(ap
, uint8
*);
85 head_size
+= va_arg(ap
, int);
92 s
= va_arg(ap
, char *);
93 head_size
+= str_charnum(s
) + 1;
99 /* allocate the space, then scan the format again to fill in the values */
100 *blob
= data_blob(NULL
, head_size
+ data_size
);
103 data_ofs
= head_size
;
105 va_start(ap
, format
);
106 for (i
=0; format
[i
]; i
++) {
109 s
= va_arg(ap
, char *);
111 SSVAL(blob
->data
, head_ofs
, n
*2); head_ofs
+= 2;
112 SSVAL(blob
->data
, head_ofs
, n
*2); head_ofs
+= 2;
113 SIVAL(blob
->data
, head_ofs
, data_ofs
); head_ofs
+= 4;
114 push_string(NULL
, blob
->data
+data_ofs
, s
, n
*2, STR_UNICODE
|STR_NOALIGN
);
118 s
= va_arg(ap
, char *);
119 n
= str_ascii_charnum(s
);
120 SSVAL(blob
->data
, head_ofs
, n
); head_ofs
+= 2;
121 SSVAL(blob
->data
, head_ofs
, n
); head_ofs
+= 2;
122 SIVAL(blob
->data
, head_ofs
, data_ofs
); head_ofs
+= 4;
123 push_string(NULL
, blob
->data
+data_ofs
, s
, n
, STR_ASCII
|STR_NOALIGN
);
127 unicode
= va_arg(ap
, BOOL
);
129 SSVAL(blob
->data
, data_ofs
, n
); data_ofs
+= 2;
130 s
= va_arg(ap
, char *);
133 SSVAL(blob
->data
, data_ofs
, n
*2); data_ofs
+= 2;
135 push_string(NULL
, blob
->data
+data_ofs
, s
, n
*2,
136 STR_UNICODE
|STR_NOALIGN
);
140 n
= str_ascii_charnum(s
);
141 SSVAL(blob
->data
, data_ofs
, n
); data_ofs
+= 2;
143 push_string(NULL
, blob
->data
+data_ofs
, s
, n
,
144 STR_ASCII
|STR_NOALIGN
);
151 b
= va_arg(ap
, uint8
*);
153 SSVAL(blob
->data
, head_ofs
, n
); head_ofs
+= 2;
154 SSVAL(blob
->data
, head_ofs
, n
); head_ofs
+= 2;
155 SIVAL(blob
->data
, head_ofs
, data_ofs
); head_ofs
+= 4;
156 if (n
&& b
) /* don't follow null pointers... */
157 memcpy(blob
->data
+data_ofs
, b
, n
);
162 SIVAL(blob
->data
, head_ofs
, n
); head_ofs
+= 4;
165 b
= va_arg(ap
, uint8
*);
167 memcpy(blob
->data
+ head_ofs
, b
, n
);
171 s
= va_arg(ap
, char *);
172 head_ofs
+= push_string(NULL
, blob
->data
+head_ofs
, s
, -1,
173 STR_ASCII
|STR_TERMINATE
);
183 /* a helpful macro to avoid running over the end of our blob */
184 #define NEED_DATA(amount) \
185 if ((head_ofs + amount) > blob->length) { \
190 this is a tiny msrpc packet parser. This the the partner of msrpc_gen
192 format specifiers are:
194 U = unicode string (output is unix string)
197 b = data blob in header
199 C = constant ascii string
202 BOOL
msrpc_parse(const DATA_BLOB
*blob
,
203 const char *format
, ...)
215 va_start(ap
, format
);
216 for (i
=0; format
[i
]; i
++) {
220 len1
= SVAL(blob
->data
, head_ofs
); head_ofs
+= 2;
221 len2
= SVAL(blob
->data
, head_ofs
); head_ofs
+= 2;
222 ptr
= IVAL(blob
->data
, head_ofs
); head_ofs
+= 4;
224 ps
= va_arg(ap
, char **);
225 if (len1
== 0 && len2
== 0) {
226 *ps
= smb_xstrdup("");
228 /* make sure its in the right format - be strict */
229 if ((len1
!= len2
) || (ptr
+ len1
< ptr
) || (ptr
+ len1
< len1
) || (ptr
+ len1
> blob
->length
)) {
233 /* if odd length and unicode */
238 pull_string(NULL
, p
, blob
->data
+ ptr
, sizeof(p
),
240 STR_UNICODE
|STR_NOALIGN
);
241 (*ps
) = smb_xstrdup(p
);
243 (*ps
) = smb_xstrdup("");
249 len1
= SVAL(blob
->data
, head_ofs
); head_ofs
+= 2;
250 len2
= SVAL(blob
->data
, head_ofs
); head_ofs
+= 2;
251 ptr
= IVAL(blob
->data
, head_ofs
); head_ofs
+= 4;
253 ps
= va_arg(ap
, char **);
254 /* make sure its in the right format - be strict */
255 if (len1
== 0 && len2
== 0) {
256 *ps
= smb_xstrdup("");
258 if ((len1
!= len2
) || (ptr
+ len1
< ptr
) || (ptr
+ len1
< len1
) || (ptr
+ len1
> blob
->length
)) {
263 pull_string(NULL
, p
, blob
->data
+ ptr
, sizeof(p
),
265 STR_ASCII
|STR_NOALIGN
);
266 (*ps
) = smb_xstrdup(p
);
268 (*ps
) = smb_xstrdup("");
274 len1
= SVAL(blob
->data
, head_ofs
); head_ofs
+= 2;
275 len2
= SVAL(blob
->data
, head_ofs
); head_ofs
+= 2;
276 ptr
= IVAL(blob
->data
, head_ofs
); head_ofs
+= 4;
278 b
= (DATA_BLOB
*)va_arg(ap
, void *);
279 if (len1
== 0 && len2
== 0) {
280 *b
= data_blob(NULL
, 0);
282 /* make sure its in the right format - be strict */
283 if ((len1
!= len2
) || (ptr
+ len1
< ptr
) || (ptr
+ len1
< len1
) || (ptr
+ len1
> blob
->length
)) {
286 *b
= data_blob(blob
->data
+ ptr
, len1
);
290 b
= (DATA_BLOB
*)va_arg(ap
, void *);
291 len1
= va_arg(ap
, unsigned);
292 /* make sure its in the right format - be strict */
294 *b
= data_blob(blob
->data
+ head_ofs
, len1
);
298 v
= va_arg(ap
, uint32
*);
300 *v
= IVAL(blob
->data
, head_ofs
); head_ofs
+= 4;
303 s
= va_arg(ap
, char *);
304 head_ofs
+= pull_string(NULL
, p
, blob
->data
+head_ofs
, sizeof(p
),
305 blob
->length
- head_ofs
,
306 STR_ASCII
|STR_TERMINATE
);
307 if (strcmp(s
, p
) != 0) {