Ticket #370: yahoo-https-authentication.diff

File yahoo-https-authentication.diff, 6.5 KB (added by wilmer, at 2008-03-15T17:38:16Z)

This patch implements the HTTPS-based authentication.

  • protocols/yahoo/libyahoo2.c

    === modified file 'protocols/yahoo/libyahoo2.c'
     
    9090#endif
    9191
    9292#include "base64.h"
     93#include "http_client.h"
    9394
    9495#ifdef USE_STRUCT_CALLBACKS
    9596struct yahoo_callbacks *yc=NULL;
     
    736737        data = y_new0(unsigned char, len + 1);
    737738
    738739        memcpy(data + pos, "YMSG", 4); pos += 4;
    739         pos += yahoo_put16(data + pos, 0x0a00);
     740        pos += yahoo_put16(data + pos, 0x000e);
    740741        pos += yahoo_put16(data + pos, 0x0000);
    741742        pos += yahoo_put16(data + pos, pktlen + extra_pad);
    742743        pos += yahoo_put16(data + pos, pkt->service);
     
    22282229        free(crypt_hash);
    22292230}
    22302231
     2232struct yahoo_https_auth_data
     2233{
     2234        struct yahoo_input_data *yid;
     2235        char *chal;
     2236};
     2237
     2238static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had);
     2239static void yahoo_https_auth_token_finish(struct http_request *req);
     2240static void yahoo_https_auth_init(struct yahoo_https_auth_data *had);
     2241static void yahoo_https_auth_finish(struct http_request *req);
     2242
     2243/* Extract a value from a login.yahoo.com response. Assume CRLF-linebreaks
     2244   and FAIL miserably if they're not there... */
     2245static char *yahoo_ha_find_key(char *response, char *key)
     2246{
     2247        char *s, *end;
     2248        int len = strlen(key);
     2249       
     2250        s = response;
     2251        do {
     2252                if (strncmp(s, key, len) == 0 && s[len] == '=') {
     2253                        s += len + 1;
     2254                        if ((end = strchr(s, '\r')))
     2255                                return g_strndup(s, end - s);
     2256                        else
     2257                                return g_strdup(s);
     2258                }
     2259               
     2260                if ((s = strchr(s, '\n')))
     2261                        s ++;
     2262        } while (s && *s);
     2263       
     2264        return NULL;
     2265}
     2266
     2267static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn)
     2268{
     2269        struct yahoo_data *yd = yid->yd;
     2270        struct yahoo_https_auth_data *had = g_new0(struct yahoo_https_auth_data, 1);
     2271       
     2272        had->yid = yid;
     2273        had->chal = g_strdup(seed);
     2274       
     2275        if (yd->token == NULL) {
     2276                yahoo_https_auth_token_init(had);
     2277        } else {
     2278                yahoo_https_auth_init(had);
     2279        }
     2280}
     2281
     2282static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had)
     2283{
     2284        struct yahoo_input_data *yid = had->yid;
     2285        struct yahoo_data *yd = yid->yd;
     2286        struct http_request *req;
     2287        char *login, *passwd, *chal;
     2288        char *url;
     2289       
     2290        login = g_strndup(yd->user, 3 * strlen(yd->user));
     2291        http_encode(login);
     2292        passwd = g_strndup(yd->password, 3 * strlen(yd->password));
     2293        http_encode(passwd);
     2294        chal = g_strndup(had->chal, 3 * strlen(had->chal));
     2295        http_encode(chal);
     2296       
     2297        url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=%d&login=%s&passwd=%s&chal=%s",
     2298                               (int) time(NULL), login, passwd, chal);
     2299       
     2300        req = http_dorequest_url(url, yahoo_https_auth_token_finish, had);
     2301       
     2302        g_free(url);
     2303}
     2304
     2305static void yahoo_https_auth_token_finish(struct http_request *req)
     2306{
     2307        struct yahoo_https_auth_data *had = req->data;
     2308        struct yahoo_input_data *yid = had->yid;
     2309        struct yahoo_data *yd = yid->yd;
     2310        int st;
     2311       
     2312        if (req->status_code != 200) {
     2313                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL);
     2314                goto fail;
     2315        }
     2316       
     2317        if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) {
     2318                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, st == 1212 ? YAHOO_LOGIN_PASSWD :
     2319                                                                        st == 1235 ? YAHOO_LOGIN_UNAME :
     2320                                                                        YAHOO_LOGIN_LOGOFF, NULL);
     2321                goto fail;
     2322        }
     2323       
     2324        if ((yd->token = yahoo_ha_find_key(req->reply_body, "ymsgr")) == NULL) {
     2325                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL);
     2326                goto fail;
     2327        }
     2328       
     2329        return yahoo_https_auth_init(had);
     2330       
     2331fail:
     2332        g_free(had->chal);
     2333        g_free(had);
     2334}
     2335
     2336static void yahoo_https_auth_init(struct yahoo_https_auth_data *had)
     2337{
     2338        struct yahoo_input_data *yid = had->yid;
     2339        struct yahoo_data *yd = yid->yd;
     2340        struct http_request *req;
     2341        char *url;
     2342       
     2343        url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=%d&token=%s",
     2344                              (int) time(NULL), yd->token);
     2345       
     2346        req = http_dorequest_url(url, yahoo_https_auth_finish, had);
     2347       
     2348        g_free(url);
     2349}
     2350
     2351static void yahoo_https_auth_finish(struct http_request *req)
     2352{
     2353        struct yahoo_https_auth_data *had = req->data;
     2354        struct yahoo_input_data *yid = had->yid;
     2355        struct yahoo_data *yd = yid->yd;
     2356        struct yahoo_packet *pack;
     2357        char *crumb;
     2358        int st;
     2359       
     2360        md5_byte_t result[16];
     2361        md5_state_t ctx;
     2362       
     2363        unsigned char yhash[32];
     2364
     2365        if (req->status_code != 200) {
     2366                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL);
     2367                goto fail;
     2368        }
     2369       
     2370        if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) {
     2371                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, st == 1212 ? YAHOO_LOGIN_PASSWD :
     2372                                                                        st == 1235 ? YAHOO_LOGIN_UNAME :
     2373                                                                        YAHOO_LOGIN_LOGOFF, NULL);
     2374                goto fail;
     2375        }
     2376       
     2377        if ((yd->cookie_y = yahoo_ha_find_key(req->reply_body, "Y")) == NULL ||
     2378            (yd->cookie_t = yahoo_ha_find_key(req->reply_body, "T")) == NULL ||
     2379            (crumb = yahoo_ha_find_key(req->reply_body, "crumb")) == NULL) {
     2380                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL);
     2381                goto fail;
     2382        }
     2383       
     2384        md5_init(&ctx); 
     2385        md5_append(&ctx, crumb, 11);
     2386        md5_append(&ctx, had->chal, strlen(had->chal));
     2387        md5_finish(&ctx, result);
     2388        to_y64(yhash, result, 16);
     2389
     2390        pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id);
     2391        yahoo_packet_hash(pack, 0, yd->user);
     2392        yahoo_packet_hash(pack, 277, yd->cookie_y);
     2393        yahoo_packet_hash(pack, 278, yd->cookie_t);
     2394        yahoo_packet_hash(pack, 307, yhash);
     2395        yahoo_packet_hash(pack, 244, "524223");
     2396        yahoo_packet_hash(pack, 2, yd->user);
     2397        yahoo_packet_hash(pack, 98, "us");
     2398        yahoo_packet_hash(pack, 135, "7.5.0.647");
     2399               
     2400        yahoo_send_packet(yid, pack, 0);
     2401               
     2402        yahoo_packet_free(pack);
     2403       
     2404        return;
     2405       
     2406fail:
     2407        g_free(had->chal);
     2408        g_free(had);
     2409}
     2410
    22312411static void yahoo_process_auth(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
    22322412{
    22332413        char *seed = NULL;
     
    22562436                case 1:
    22572437                        yahoo_process_auth_0x0b(yid, seed, sn);
    22582438                        break;
     2439                case 2:
     2440                        yahoo_https_auth(yid, seed, sn);
     2441                        break;
    22592442                default:
    22602443                        /* call error */
    22612444                        WARNING(("unknown auth type %d", m));
  • protocols/yahoo/yahoo2_types.h

    === modified file 'protocols/yahoo/yahoo2_types.h'
     
    159159struct yahoo_data {
    160160        char  *user;
    161161        char  *password;
     162        char  *token;
    162163
    163164        char  *cookie_y;
    164165        char  *cookie_t;