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 3 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, see <http://www.gnu.org/licenses/>.
25
this is a tiny msrpc packet generator. I am only using this to
26
avoid tying this code to a particular varient of our rpc code. This
27
generator is not general enough for all our rpc needs, its just
28
enough for the spnego/ntlmssp code
30
format specifiers are:
32
U = unicode string (input is unix string)
33
a = address (input is char *unix_string)
34
(1 byte type, 1 byte length, unicode/ASCII string, all inline)
35
A = ASCII string (input is unix string)
36
B = data blob (pointer + length)
37
b = data blob in header (pointer + length)
40
C = constant ascii string
42
bool msrpc_gen(DATA_BLOB *blob,
43
const char *format, ...)
49
int head_size=0, data_size=0;
50
int head_ofs, data_ofs;
52
/* first scan the format to work out the header and body size */
54
for (i=0; format[i]; i++) {
57
s = va_arg(ap, char *);
59
data_size += str_charnum(s) * 2;
62
s = va_arg(ap, char *);
64
data_size += str_ascii_charnum(s);
68
s = va_arg(ap, char *);
69
data_size += (str_charnum(s) * 2) + 4;
72
b = va_arg(ap, uint8 *);
74
data_size += va_arg(ap, int);
77
b = va_arg(ap, uint8 *);
78
head_size += va_arg(ap, int);
85
s = va_arg(ap, char *);
86
head_size += str_charnum(s) + 1;
92
/* allocate the space, then scan the format
93
* again to fill in the values */
95
*blob = data_blob(NULL, head_size + data_size);
100
va_start(ap, format);
101
for (i=0; format[i]; i++) {
104
s = va_arg(ap, char *);
106
SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
107
SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
108
SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
109
push_string(NULL, blob->data+data_ofs,
110
s, n*2, STR_UNICODE|STR_NOALIGN);
114
s = va_arg(ap, char *);
115
n = str_ascii_charnum(s);
116
SSVAL(blob->data, head_ofs, n); head_ofs += 2;
117
SSVAL(blob->data, head_ofs, n); head_ofs += 2;
118
SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
119
push_string(NULL, blob->data+data_ofs,
120
s, n, STR_ASCII|STR_NOALIGN);
125
SSVAL(blob->data, data_ofs, n); data_ofs += 2;
126
s = va_arg(ap, char *);
128
SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
130
push_string(NULL, blob->data+data_ofs, s, n*2,
131
STR_UNICODE|STR_NOALIGN);
137
b = va_arg(ap, uint8 *);
139
SSVAL(blob->data, head_ofs, n); head_ofs += 2;
140
SSVAL(blob->data, head_ofs, n); head_ofs += 2;
141
SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
142
if (n && b) /* don't follow null pointers... */
143
memcpy(blob->data+data_ofs, b, n);
148
SIVAL(blob->data, head_ofs, n); head_ofs += 4;
151
b = va_arg(ap, uint8 *);
153
memcpy(blob->data + head_ofs, b, n);
157
s = va_arg(ap, char *);
158
n = str_charnum(s) + 1;
159
head_ofs += push_string(NULL, blob->data+head_ofs, s, n,
160
STR_ASCII|STR_TERMINATE);
170
/* a helpful macro to avoid running over the end of our blob */
171
#define NEED_DATA(amount) \
172
if ((head_ofs + amount) > blob->length) { \
178
this is a tiny msrpc packet parser. This the the partner of msrpc_gen
180
format specifiers are:
182
U = unicode string (output is unix string)
185
b = data blob in header
187
C = constant ascii string
190
bool msrpc_parse(const DATA_BLOB *blob,
191
const char *format, ...)
202
va_start(ap, format);
203
for (i=0; format[i]; i++) {
207
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
208
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
209
ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
211
ps = va_arg(ap, char **);
212
if (len1 == 0 && len2 == 0) {
213
*ps = smb_xstrdup("");
215
/* make sure its in the right format
217
if ((len1 != len2) || (ptr + len1 < ptr) ||
218
(ptr + len1 < len1) ||
219
(ptr + len1 > blob->length)) {
224
/* if odd length and unicode */
228
if (blob->data + ptr <
229
(uint8 *)(unsigned long)ptr ||
230
blob->data + ptr < blob->data) {
237
pull_string_talloc(talloc_tos(),
243
STR_UNICODE|STR_NOALIGN);
245
(*ps) = smb_xstrdup(p);
248
(*ps) = smb_xstrdup("");
251
(*ps) = smb_xstrdup("");
257
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
258
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
259
ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
261
ps = va_arg(ap, char **);
262
/* make sure its in the right format - be strict */
263
if (len1 == 0 && len2 == 0) {
264
*ps = smb_xstrdup("");
266
if ((len1 != len2) || (ptr + len1 < ptr) ||
267
(ptr + len1 < len1) ||
268
(ptr + len1 > blob->length)) {
273
if (blob->data + ptr <
274
(uint8 *)(unsigned long)ptr ||
275
blob->data + ptr < blob->data) {
282
pull_string_talloc(talloc_tos(),
288
STR_ASCII|STR_NOALIGN);
290
(*ps) = smb_xstrdup(p);
293
(*ps) = smb_xstrdup("");
296
(*ps) = smb_xstrdup("");
302
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
303
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
304
ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
306
b = (DATA_BLOB *)va_arg(ap, void *);
307
if (len1 == 0 && len2 == 0) {
310
/* make sure its in the right format
312
if ((len1 != len2) || (ptr + len1 < ptr) ||
313
(ptr + len1 < len1) ||
314
(ptr + len1 > blob->length)) {
319
if (blob->data + ptr <
320
(uint8 *)(unsigned long)ptr ||
321
blob->data + ptr < blob->data) {
326
*b = data_blob(blob->data + ptr, len1);
330
b = (DATA_BLOB *)va_arg(ap, void *);
331
len1 = va_arg(ap, unsigned);
332
/* make sure its in the right format - be strict */
334
if (blob->data + head_ofs < (uint8 *)head_ofs ||
335
blob->data + head_ofs < blob->data) {
340
*b = data_blob(blob->data + head_ofs, len1);
344
v = va_arg(ap, uint32 *);
346
*v = IVAL(blob->data, head_ofs); head_ofs += 4;
349
s = va_arg(ap, char *);
351
if (blob->data + head_ofs < (uint8 *)head_ofs ||
352
blob->data + head_ofs < blob->data) {
359
size_t ret = pull_string_talloc(talloc_tos(),
364
blob->length - head_ofs,
365
STR_ASCII|STR_TERMINATE);
366
if (ret == (size_t)-1 || p == NULL) {
371
if (strcmp(s, p) != 0) {