Mercurial > pidgin.yaz
comparison libfaim/aim_login.c @ 741:58a6e6e26695
[gaim-migrate @ 751]
oscar logins work better (?), aliases in convo windows.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Tue, 22 Aug 2000 23:38:47 +0000 |
parents | 58106806ac2b |
children | 72e556f6b99d |
comparison
equal
deleted
inserted
replaced
740:01d3c96867e2 | 741:58a6e6e26695 |
---|---|
5 * | 5 * |
6 */ | 6 */ |
7 | 7 |
8 #include <faim/aim.h> | 8 #include <faim/aim.h> |
9 | 9 |
10 #include "md5.h" | |
11 | |
12 static int aim_encode_password_md5(const char *password, const char *key, md5_byte_t *digest); | |
10 | 13 |
11 /* | 14 /* |
12 * FIXME: Reimplement the TIS stuff. | 15 * FIXME: Reimplement the TIS stuff. |
13 */ | 16 */ |
14 #ifdef TIS_TELNET_PROXY | 17 #ifdef TIS_TELNET_PROXY |
32 | 35 |
33 newpacket->lock = 0; | 36 newpacket->lock = 0; |
34 return aim_tx_enqueue(sess, newpacket); | 37 return aim_tx_enqueue(sess, newpacket); |
35 } | 38 } |
36 | 39 |
37 #ifdef SNACLOGIN | |
38 /* | 40 /* |
39 * In AIM 3.5 protocol, the first stage of login is to request | 41 * In AIM 3.5 protocol, the first stage of login is to request |
40 * login from the Authorizer, passing it the screen name | 42 * login from the Authorizer, passing it the screen name |
41 * for verification. If the name is invalid, a 0017/0003 | 43 * for verification. If the name is invalid, a 0017/0003 |
42 * is spit back, with the standard error contents. If valid, | 44 * is spit back, with the standard error contents. If valid, |
60 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); | 62 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); |
61 | 63 |
62 newpacket->lock = 0; | 64 newpacket->lock = 0; |
63 return aim_tx_enqueue(sess, newpacket); | 65 return aim_tx_enqueue(sess, newpacket); |
64 } | 66 } |
65 #endif /* SNACLOGIN */ | |
66 | 67 |
67 /* | 68 /* |
68 * send_login(int socket, char *sn, char *password) | 69 * send_login(int socket, char *sn, char *password) |
69 * | 70 * |
70 * This is the initial login request packet. | 71 * This is the initial login request packet. |
74 * stupid method of doing it. | 75 * stupid method of doing it. |
75 * | 76 * |
76 */ | 77 */ |
77 int aim_send_login (struct aim_session_t *sess, | 78 int aim_send_login (struct aim_session_t *sess, |
78 struct aim_conn_t *conn, | 79 struct aim_conn_t *conn, |
79 char *sn, char *password, struct client_info_s *clientinfo) | 80 char *sn, char *password, struct client_info_s *clientinfo, |
80 { | 81 char *key) |
81 u_char *password_encoded = NULL; /* to store encoded password */ | 82 { |
82 int curbyte=0; | 83 int curbyte=0; |
83 int icqmode = 0; | 84 md5_byte_t digest[16]; |
84 | 85 |
85 struct command_tx_struct *newpacket; | 86 struct command_tx_struct *newpacket; |
86 | 87 |
87 if (!clientinfo || !sn || !password) | 88 if (!clientinfo || !sn || !password) |
88 return -1; | 89 return -1; |
89 | 90 |
90 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152))) | 91 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152))) |
91 return -1; | 92 return -1; |
92 | 93 |
93 /* | |
94 * For ICQ logins, the client version must be at | |
95 * least as high as ICQ2000a. | |
96 */ | |
97 if ((sn[0] >= '0') && (sn[0] <= '9')) { | |
98 icqmode = 1; /* needs a different password encoding */ | |
99 if (clientinfo && (clientinfo->major < 4)) { | |
100 printf("faim: icq: version must be at least 4.30.3141 for ICQ OSCAR login\n"); | |
101 } | |
102 if (strlen(password) > 8) { | |
103 printf("faim: icq: password too long (8 char max)\n"); | |
104 } | |
105 } | |
106 | |
107 #ifdef SNACLOGIN | |
108 newpacket->commandlen = 10; | |
109 newpacket->commandlen += 2 + 2 + strlen(sn); | |
110 newpacket->commandlen += 2 + 2 + strlen(password); | |
111 newpacket->commandlen += 2 + 2 + strlen(clientinfo->clientstring); | |
112 newpacket->commandlen += 56; | |
113 | |
114 newpacket->lock = 1; | 94 newpacket->lock = 1; |
115 | 95 |
96 newpacket->hdr.oscar.type = 0x02; | |
97 | |
116 curbyte = aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0002, 0x0000, 0x00010000); | 98 curbyte = aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0002, 0x0000, 0x00010000); |
99 | |
117 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); | 100 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); |
118 password_encoded = (u_char *) malloc(strlen(password)); | 101 |
119 aim_encode_password(password, password_encoded); | 102 aim_encode_password_md5(password, key, digest); |
120 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded); | 103 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, digest); |
121 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0003, | |
122 strlen(clientinfo->clientstring), | |
123 clientinfo->clientstring); | |
124 /* XXX: should use clientinfo provided version info */ | |
125 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x0004); | |
126 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0003); | |
127 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x0005); | |
128 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0000); | |
129 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0686); | |
130 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, 0x0002, clientinfo->country); | |
131 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, 0x0002, clientinfo->lang); | |
132 curbyte+= aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x0000002a); | |
133 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015); | |
134 #else | |
135 | |
136 newpacket->lock = 1; | |
137 newpacket->hdr.oscar.type = 0x01; | |
138 | |
139 /* | |
140 * These four bytes are actually the FLAP version information. | |
141 * They're sent here for convenience. I suppose they could | |
142 * be seperated out into a seperate FLAP, but this is where | |
143 * everyone else sends them. | |
144 */ | |
145 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
146 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); | |
147 | |
148 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); | |
149 | |
150 password_encoded = (char *) malloc(strlen(password)); | |
151 aim_encode_password(password, password_encoded); | |
152 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded); | |
153 free(password_encoded); | |
154 | 104 |
155 /* XXX is clientstring required by oscar? */ | 105 /* XXX is clientstring required by oscar? */ |
156 if (strlen(clientinfo->clientstring)) | 106 if (strlen(clientinfo->clientstring)) |
157 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); | 107 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); |
158 | 108 |
159 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, clientinfo->major2); | 109 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, clientinfo->major2); |
160 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, clientinfo->major); | 110 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, clientinfo->major); |
161 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, clientinfo->minor); | 111 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, clientinfo->minor); |
162 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, clientinfo->minor2); | 112 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, clientinfo->minor2); |
163 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, clientinfo->build); | 113 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, clientinfo->build); |
164 | 114 |
165 curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); | 115 curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); |
116 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015); | |
166 | 117 |
167 if (strlen(clientinfo->country)) | 118 if (strlen(clientinfo->country)) |
168 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country); | 119 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country); |
169 else | 120 else |
170 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, 2, "us"); | 121 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, 2, "us"); |
173 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang); | 124 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang); |
174 else | 125 else |
175 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, 2, "en"); | 126 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, 2, "en"); |
176 | 127 |
177 newpacket->commandlen = curbyte; | 128 newpacket->commandlen = curbyte; |
178 #endif | |
179 | 129 |
180 newpacket->lock = 0; | 130 newpacket->lock = 0; |
181 return aim_tx_enqueue(sess, newpacket); | 131 return aim_tx_enqueue(sess, newpacket); |
132 } | |
133 | |
134 static int aim_encode_password_md5(const char *password, const char *key, md5_byte_t *digest) | |
135 { | |
136 md5_state_t state; | |
137 | |
138 md5_init(&state); | |
139 md5_append(&state, (const md5_byte_t *)key, strlen(key)); | |
140 md5_append(&state, (const md5_byte_t *)password, strlen(password)); | |
141 md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); | |
142 md5_finish(&state, (md5_byte_t *)digest); | |
143 | |
144 return 0; | |
182 } | 145 } |
183 | 146 |
184 /* | 147 /* |
185 * int encode_password( | 148 * int encode_password( |
186 * const char *password, | 149 * const char *password, |
194 * the null. The encoded password buffer IS NOT NULL TERMINATED. | 157 * the null. The encoded password buffer IS NOT NULL TERMINATED. |
195 * | 158 * |
196 * The encoding_table seems to be a fixed set of values. We'll | 159 * The encoding_table seems to be a fixed set of values. We'll |
197 * hope it doesn't change over time! | 160 * hope it doesn't change over time! |
198 * | 161 * |
199 */ | 162 * NOTE: This is no longer used. Its here for historical reference. |
200 int aim_encode_password(const char *password, u_char *encoded) | 163 * |
164 */ | |
165 #if 0 | |
166 static int aim_encode_password(const char *password, unsigned char *encoded) | |
201 { | 167 { |
202 u_char encoding_table[] = { | 168 u_char encoding_table[] = { |
203 #if 0 /* old v1 table */ | 169 #if 0 /* old v1 table */ |
204 0xf3, 0xb3, 0x6c, 0x99, | 170 0xf3, 0xb3, 0x6c, 0x99, |
205 0x95, 0x3f, 0xac, 0xb6, | 171 0x95, 0x3f, 0xac, 0xb6, |
218 for (i = 0; i < strlen(password); i++) | 184 for (i = 0; i < strlen(password); i++) |
219 encoded[i] = (password[i] ^ encoding_table[i]); | 185 encoded[i] = (password[i] ^ encoding_table[i]); |
220 | 186 |
221 return 0; | 187 return 0; |
222 } | 188 } |
189 #endif | |
223 | 190 |
224 /* | 191 /* |
225 * This is sent back as a general response to the login command. | 192 * This is sent back as a general response to the login command. |
226 * It can be either an error or a success, depending on the | 193 * It can be either an error or a success, depending on the |
227 * precense of certain TLVs. | 194 * precense of certain TLVs. |
241 memset(&sess->logininfo, 0x00, sizeof(sess->logininfo)); | 208 memset(&sess->logininfo, 0x00, sizeof(sess->logininfo)); |
242 | 209 |
243 /* | 210 /* |
244 * Read block of TLVs. All further data is derived | 211 * Read block of TLVs. All further data is derived |
245 * from what is parsed here. | 212 * from what is parsed here. |
213 * | |
214 * For SNAC login, there's a 17/3 SNAC header in front. | |
215 * | |
246 */ | 216 */ |
247 #ifdef SNACLOGIN | |
248 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10); | 217 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10); |
249 #else | 218 |
250 tlvlist = aim_readtlvchain(command->data, command->commandlen); | |
251 #endif | |
252 /* | 219 /* |
253 * No matter what, we should have a screen name. | 220 * No matter what, we should have a screen name. |
254 */ | 221 */ |
255 sn = aim_gettlv_str(tlvlist, 0x0001, 1); | 222 sn = aim_gettlv_str(tlvlist, 0x0001, 1); |
256 strncpy(sess->logininfo.screen_name, sn, strlen(sn)); | 223 strncpy(sess->logininfo.screen_name, sn, strlen(sn)); |
299 if ((tmptlv = aim_gettlv(tlvlist, 0x0013, 1))) | 266 if ((tmptlv = aim_gettlv(tlvlist, 0x0013, 1))) |
300 sess->logininfo.regstatus = aimutil_get16(tmptlv->value); | 267 sess->logininfo.regstatus = aimutil_get16(tmptlv->value); |
301 | 268 |
302 } | 269 } |
303 | 270 |
304 #ifdef SNACLOGIN | |
305 userfunc = aim_callhandler(command->conn, 0x0017, 0x0003); | 271 userfunc = aim_callhandler(command->conn, 0x0017, 0x0003); |
306 #else | 272 |
307 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS); | |
308 #endif | |
309 if (userfunc) | 273 if (userfunc) |
310 ret = userfunc(sess, command); | 274 ret = userfunc(sess, command); |
311 | 275 |
312 aim_freetlvchain(&tlvlist); | 276 aim_freetlvchain(&tlvlist); |
313 | 277 |
321 } | 285 } |
322 if (sess->logininfo.errorurl) { | 286 if (sess->logininfo.errorurl) { |
323 free(sess->logininfo.errorurl); | 287 free(sess->logininfo.errorurl); |
324 sess->logininfo.errorurl = NULL; | 288 sess->logininfo.errorurl = NULL; |
325 } | 289 } |
290 | |
291 return ret; | |
292 } | |
293 | |
294 /* | |
295 * Middle handler for 0017/0007 SNACs. Contains the auth key prefixed | |
296 * by only its length in a two byte word. | |
297 * | |
298 * Calls the client, which should then use the value to call aim_send_login. | |
299 * | |
300 */ | |
301 int aim_authkeyparse(struct aim_session_t *sess, struct command_rx_struct *command) | |
302 { | |
303 unsigned char *key; | |
304 int keylen; | |
305 int ret = 1; | |
306 rxcallback_t userfunc; | |
307 | |
308 keylen = aimutil_get16(command->data+10); | |
309 key = malloc(keylen+1); | |
310 memcpy(key, command->data+12, keylen); | |
311 key[keylen] = '\0'; | |
312 | |
313 if ((userfunc = aim_callhandler(command->conn, 0x0017, 0x0007))) | |
314 ret = userfunc(sess, command, key); | |
315 | |
316 free(key); | |
326 | 317 |
327 return ret; | 318 return ret; |
328 } | 319 } |
329 | 320 |
330 /* | 321 /* |