-
Notifications
You must be signed in to change notification settings - Fork 44
/
decode_tds.c
206 lines (171 loc) · 4.01 KB
/
decode_tds.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
* decode_tds.c
*
* Tabular Data Stream (Sybase, Microsoft SQL). See www.freetds.org.
*
* Thanks to antilove!@#$% and Ben Lowery <[email protected]> for
* providing me with packet traces.
*
* Copyright (c) 2000 Dug Song <[email protected]>
* Copyright (c) 2001 Paul van Maaren <[email protected]>
*
* $Id: decode_tds.c,v 1.10 2001/03/15 08:33:02 dugsong Exp $
*/
#include "config.h"
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include "decode.h"
struct tds_hdr {
u_char type;
u_char last;
u_short size;
u_int32_t zero;
};
struct tds_login {
char hostname[30];
u_char hostlen;
char username[30];
u_char userlen;
char password[30];
u_char passlen;
char process[30];
u_char proclen;
char magic1[6];
u_char bulkcopy;
char magic2[9];
char appname[30];
u_char applen;
char servername[30];
u_char serverlen;
u_char zero;
u_char pass2len;
char password2[30];
char magic3[223];
u_char pass2len2;
char version[4];
char libname[10];
u_char liblen;
char magic4[3];
char language[30];
u_char langlen;
u_char nolang;
u_short magic5;
u_char encrypted;
char magic6[10];
char charset[30];
u_char charlen;
u_char magic7;
char blocksize[6];
u_char blocklen;
char magic8[4]; /* 4.2: 8, 4.6: 4, 5.0: 25 */
};
u_char tds7_magic1[] = {
0x6, 0x83, 0xf2, 0xf8, 0xff, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x03, 0x0,
0x0, 0x88, 0xff, 0xff, 0xff, 0x36, 0x04, 0x00, 0x00
};
struct tds7_login {
u_short size;
char zero1[5];
u_char byte1; /* 0x70 */
char zero2[7];
char magic1[21];
u_short servpos;
u_short servlen;
u_short userpos; /* XXX - freetds got this wrong? */
u_short userlen;
u_short passpos;
u_short passlen;
u_short somepos;
u_short somelen;
u_short apppos;
u_short applen;
char zero4[4];
u_short libpos;
u_short liblen;
char skip1[8];
char magic2[6];
char skip2[8];
/* char servername[servlen]; */
/* char username[userlen]; */
/* char password[passlen]; */
/* char appname[applen]; */
/* char server[servlen]; */
/* char library[liblen]; */
/* char magic3[48]; */
};
static void
deunicode(u_char *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
buf[i] = buf[i * 2];
}
buf[i] = '\0';
}
static void
tds7_decrypt(u_char *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
buf[i] = ((buf[i] << 4) | (buf[i] >> 4)) ^ 0x5a;
}
buf[i] = '\0';
}
int
decode_tds(u_char *buf, int len, u_char *obuf, int olen)
{
struct tds_hdr *th;
struct tds_login *tl;
struct tds7_login *t7l, *myt7l;
u_char *user, *pass, *serv;
u_short userlen, passlen, servlen;
obuf[0] = '\0';
for (th = (struct tds_hdr *)buf;
len > sizeof(*th) && len >= ntohs(th->size);
buf += ntohs(th->size), len -= ntohs(th->size)) {
if (th->type == 2) {
/* Version 4.x, 5.0 */
if (len < sizeof(*th) + sizeof(*tl))
return (0);
tl = (struct tds_login *)(th + 1);
if (tl->userlen > sizeof(tl->username))
return (0);
tl->username[tl->userlen] = '\0';
strlcat(obuf, tl->username, olen);
strlcat(obuf, "\n", olen);
if (tl->passlen > sizeof(tl->password))
return (0);
tl->password[tl->passlen] = '\0';
strlcat(obuf, tl->password, olen);
strlcat(obuf, "\n", olen);
}
else if (th->type == 16 && th->last == 1) {
/* Version 7.0 */
if (len < sizeof(*th) + sizeof(*t7l))
return (0);
t7l = (struct tds7_login *)(th + 1);
myt7l = (struct tds7_login *)(buf + sizeof(*th));
userlen = pletohs(&t7l->userlen);
passlen = pletohs(&t7l->passlen);
servlen = pletohs(&t7l->servlen);
if (len < sizeof(*th) + sizeof(*t7l) +
(2 * (userlen + passlen))) {
return (0);
}
serv = (u_char *)(t7l + 1);
deunicode(serv, servlen);
user = serv + (2 * servlen);
pass = user + (2 * userlen);
deunicode(user, userlen);
/* XXX - when to call? */
tds7_decrypt(pass, 2 * passlen);
deunicode(pass, passlen);
snprintf(obuf + strlen(obuf),
olen - strlen(obuf),
"%s\n%s\n", user, pass);
return(strlen(obuf));
}
}
return (strlen(obuf));
}