Annotation of libwww/Library/src/HTAABrow.c, revision 2.10

2.1       luotonen    1: 
                      2: /* MODULE                                                      HTAABrow.c
                      3: **             BROWSER SIDE ACCESS AUTHORIZATION MODULE
                      4: **
                      5: **     Containts the code for keeping track on server hostnames,
                      6: **     port numbers, scheme names, usernames, passwords
                      7: **     (and servers' public keys).
                      8: **
                      9: ** IMPORTANT:
                     10: **     Routines in this module use dynamic allocation, but free
                     11: **     automatically all the memory reserved by them.
                     12: **
                     13: **     Therefore the caller never has to (and never should)
                     14: **     free() any object returned by these functions.
                     15: **
                     16: **     Therefore also all the strings returned by this package
                     17: **     are only valid until the next call to the same function
                     18: **     is made. This approach is selected, because of the nature
                     19: **     of access authorization: no string returned by the package
                     20: **     needs to be valid longer than until the next call.
                     21: **
                     22: **     This also makes it easy to plug the AA package in:
                     23: **     you don't have to ponder whether to free() something
                     24: **     here or is it done somewhere else (because it is always
                     25: **     done somewhere else).
                     26: **
                     27: **     The strings that the package needs to store are copied
                     28: **     so the original strings given as parameters to AA
                     29: **     functions may be freed or modified with no side effects.
                     30: **
                     31: **     The AA package does not free() anything else than what
                     32: **     it has itself allocated.
                     33: **
                     34: ** AUTHORS:
                     35: **     AL      Ari Luotonen    luotonen@dxcern.cern.ch
                     36: **
                     37: ** HISTORY:
2.5       luotonen   38: **     Oct 17  AL      Made corrections suggested by marca:
                     39: **                     Added  if (!realm->username) return NULL;
                     40: **                     Changed some ""s to NULLs.
                     41: **                     Now doing calloc() to init uuencode source;
                     42: **                     otherwise HTUU_encode() reads uninitialized memory
                     43: **                     every now and then (not a real bug but not pretty).
                     44: **                     Corrected the formula for uuencode destination size.
2.1       luotonen   45: ** BUGS:
                     46: **
                     47: **
                     48: */
                     49: 
                     50: #include <string.h>            /* strchr() */
                     51: 
                     52: #include "HTUtils.h"
                     53: #include "HTString.h"
                     54: #include "HTParse.h"           /* URL parsing function         */
                     55: #include "HTList.h"            /* HTList object                */
                     56: #include "HTAlert.h"           /* HTConfirm(), HTPrompt()      */
                     57: #include "HTAAUtil.h"          /* AA common to both sides      */
2.2       luotonen   58: #include "HTAssoc.h"           /* Assoc list                   */
2.1       luotonen   59: #include "HTAABrow.h"          /* Implemented here             */
                     60: #include "HTUU.h"              /* Uuencoding and uudecoding    */
2.7       luotonen   61: #include "HTAccess.h"          /* HTRequest structure          */
2.1       luotonen   62: 
                     63: 
                     64: /*
                     65: ** Module-wide global variables
                     66: */
                     67: 
                     68: PRIVATE HTList *server_table   = NULL; /* Browser's info about servers      */
2.7       luotonen   69: 
2.1       luotonen   70: 
                     71: /**************************** HTAAServer ***********************************/
                     72: 
                     73: 
                     74: /* PRIVATE                                             HTAAServer_new()
                     75: **             ALLOCATE A NEW NODE TO HOLD SERVER INFO
                     76: **             AND ADD IT TO THE LIST OF SERVERS
                     77: ** ON ENTRY:
                     78: **     hostname        is the name of the host that the server
                     79: **                     is running in.
                     80: **     portnumber      is the portnumber which the server listens.
                     81: **
                     82: ** ON EXIT:
                     83: **     returns         the newly-allocated node with all the strings
                     84: **                     duplicated.
                     85: **                     Strings will be automatically freed by
                     86: **                     the function HTAAServer_delete(), which also
                     87: **                     frees the node itself.
                     88: */
                     89: PRIVATE HTAAServer *HTAAServer_new ARGS2(CONST char*,  hostname,
                     90:                                         int,           portnumber)
                     91: {
                     92:     HTAAServer *server;
                     93: 
                     94:     if (!(server = (HTAAServer *)malloc(sizeof(HTAAServer))))
                     95:        outofmem(__FILE__, "HTAAServer_new");
                     96: 
                     97:     server->hostname   = NULL;
                     98:     server->portnumber = (portnumber > 0 ? portnumber : 80);
                     99:     server->setups     = HTList_new();
2.4       luotonen  100:     server->realms     = HTList_new();
2.1       luotonen  101: 
                    102:     if (hostname) StrAllocCopy(server->hostname, hostname);
                    103: 
                    104:     if (!server_table) server_table = HTList_new();
                    105:     
                    106:     HTList_addObject(server_table, (void*)server);
                    107: 
                    108:     return server;
                    109: }
                    110: 
                    111: 
                    112: /* PRIVATE                                             HTAAServer_delete()
                    113: **
                    114: **     DELETE THE ENTRY FOR THE SERVER FROM THE HOST TABLE,
                    115: **     AND FREE THE MEMORY USED BY IT.
                    116: **
                    117: ** ON ENTRY:
                    118: **     killme          points to the HTAAServer to be freed.
                    119: **
                    120: ** ON EXIT:
                    121: **     returns         nothing.
                    122: */
                    123: #ifdef NOT_NEEDED_IT_SEEMS
                    124: PRIVATE void HTAASetup_delete();       /* Forward */
                    125: PRIVATE void HTAAServer_delete ARGS1(HTAAServer *, killme)
                    126: {
                    127:     if (killme) {
2.4       luotonen  128:        HTList *cur1 = killme->setups;
                    129:        HTList *cur2 = killme->realms;
2.1       luotonen  130:        HTAASetup *setup;
2.4       luotonen  131:        HTAARealm *realm;
2.1       luotonen  132: 
2.4       luotonen  133:        while (NULL != (setup = (HTAASetup*)HTList_nextObject(cur1)))
2.1       luotonen  134:            HTAASetup_delete(setup);
                    135:        HTList_delete(killme->setups);
                    136: 
2.4       luotonen  137:        while (NULL != (realm = (HTAARealm*)HTList_nextObject(cur2)))
                    138:            ;   /* This sould free() the realm */
                    139:        HTList_delete(killme->realms);
                    140: 
2.1       luotonen  141:        FREE(killme->hostname);
                    142: 
                    143:        HTList_removeObject(server_table, (void*)killme);
                    144: 
                    145:        free(killme);
                    146:     }
                    147: }
                    148: #endif /*NOT_NEEDED_IT_SEEMS*/
                    149: 
                    150: 
                    151: /* PRIVATE                                             HTAAServer_lookup()
                    152: **             LOOK UP SERVER BY HOSTNAME AND PORTNUMBER
                    153: ** ON ENTRY:
                    154: **     hostname        obvious.
                    155: **     portnumber      if non-positive defaults to 80.
                    156: **
                    157: **     Looks up the server in the module-global server_table.
                    158: **
                    159: ** ON EXIT:
                    160: **     returns         pointer to a HTAAServer structure
                    161: **                     representing the looked-up server.
                    162: **                     NULL, if not found.
                    163: */
                    164: PRIVATE HTAAServer *HTAAServer_lookup ARGS2(CONST char *, hostname,
                    165:                                            int,          portnumber)
                    166: {
                    167:     if (hostname) {
                    168:        HTList *cur = server_table;
                    169:        HTAAServer *server;
                    170: 
                    171:        if (portnumber <= 0) portnumber = 80;
                    172: 
                    173:        while (NULL != (server = (HTAAServer*)HTList_nextObject(cur))) {
                    174:            if (server->portnumber == portnumber  &&
                    175:                0==strcmp(server->hostname, hostname))
                    176:                return server;
                    177:        }
                    178:     }
                    179:     return NULL;       /* NULL parameter, or not found */
                    180: }
                    181: 
                    182: 
                    183: 
                    184: 
                    185: /*************************** HTAASetup *******************************/    
                    186: 
                    187: 
                    188: /* PRIVATE                                             HTAASetup_lookup()
                    189: **     FIGURE OUT WHICH AUTHENTICATION SETUP THE SERVER
                    190: **     IS USING FOR A GIVEN FILE ON A GIVEN HOST AND PORT
                    191: **
                    192: ** ON ENTRY:
                    193: **     hostname        is the name of the server host machine.
                    194: **     portnumber      is the port that the server is running in.
                    195: **     docname         is the (URL-)pathname of the document we
                    196: **                     are trying to access.
                    197: **
                    198: **     This function goes through the information known about
                    199: **     all the setups of the server, and finds out if the given
                    200: **     filename resides in one of the protected directories.
                    201: **
                    202: ** ON EXIT:
                    203: **     returns         NULL if no match.
                    204: **                     Otherwise, a HTAASetup structure representing
                    205: **                     the protected server setup on the corresponding
                    206: **                     document tree.
                    207: **                     
                    208: */
                    209: PRIVATE HTAASetup *HTAASetup_lookup ARGS3(CONST char *, hostname,
                    210:                                          int,          portnumber,
                    211:                                          CONST char *, docname)
                    212: {
                    213:     HTAAServer *server;
                    214:     HTAASetup *setup;
                    215: 
                    216:     if (portnumber <= 0) portnumber = 80;
                    217: 
                    218:     if (hostname && docname && *hostname && *docname &&
                    219:        NULL != (server = HTAAServer_lookup(hostname, portnumber))) {
                    220: 
                    221:        HTList *cur = server->setups;
                    222: 
                    223:        if (TRACE) fprintf(stderr, "%s (%s:%d:%s)\n",
                    224:                           "HTAASetup_lookup: resolving setup for",
                    225:                           hostname, portnumber, docname);
                    226: 
                    227:        while (NULL != (setup = (HTAASetup*)HTList_nextObject(cur))) {
                    228:            if (HTAA_templateMatch(setup->template, docname)) {
                    229:                if (TRACE) fprintf(stderr, "%s `%s' %s `%s'\n",
                    230:                                   "HTAASetup_lookup:", docname,
                    231:                                   "matched template", setup->template);
                    232:                return setup;
                    233:            }
                    234:            else if (TRACE) fprintf(stderr, "%s `%s' %s `%s'\n",
                    235:                                    "HTAASetup_lookup:", docname,
                    236:                                    "did NOT match template", setup->template);
                    237:        } /* while setups remain */
                    238:     } /* if valid parameters and server found */
                    239: 
                    240:     if (TRACE) fprintf(stderr, "%s `%s' %s\n",
                    241:                       "HTAASetup_lookup: No template matched",
                    242:                       (docname ? docname : "(null)"),
                    243:                       "(so probably not protected)");
                    244: 
                    245:     return NULL;       /* NULL in parameters, or not found */
                    246: }
                    247: 
                    248: 
                    249: 
                    250: 
                    251: /* PRIVATE                                             HTAASetup_new()
                    252: **                     CREATE A NEW SETUP NODE
                    253: ** ON ENTRY:
                    254: **     server          is a pointer to a HTAAServer structure
                    255: **                     to which this setup belongs.
                    256: **     template        documents matching this template
                    257: **                     are protected according to this setup.
2.2       luotonen  258: **     valid_schemes   a list containing all valid authentication
                    259: **                     schemes for this setup.
2.1       luotonen  260: **                     If NULL, all schemes are disallowed.
2.2       luotonen  261: **     scheme_specifics is an array of assoc lists, which
                    262: **                     contain scheme specific parameters given
                    263: **                     by server in Authenticate: fields.
2.1       luotonen  264: **                     If NULL, all scheme specifics are
                    265: **                     set to NULL.
                    266: ** ON EXIT:
                    267: **     returns         a new HTAASetup node, and also adds it as
                    268: **                     part of the HTAAServer given as parameter.
                    269: */
                    270: PRIVATE HTAASetup *HTAASetup_new ARGS4(HTAAServer *,   server,
                    271:                                       char *,          template,
2.2       luotonen  272:                                       HTList *,        valid_schemes,
                    273:                                       HTAssocList **,  scheme_specifics)
2.1       luotonen  274: {
                    275:     HTAASetup *setup;
                    276: 
                    277:     if (!server || !template || !*template) return NULL;
                    278: 
                    279:     if (!(setup = (HTAASetup*)malloc(sizeof(HTAASetup))))
                    280:        outofmem(__FILE__, "HTAASetup_new");
                    281: 
2.7       luotonen  282:     setup->reprompt = NO;
2.1       luotonen  283:     setup->server = server;
                    284:     setup->template = NULL;
2.2       luotonen  285:     if (template) StrAllocCopy(setup->template, template);
                    286:     setup->valid_schemes = valid_schemes;
                    287:     setup->scheme_specifics = scheme_specifics;
2.1       luotonen  288: 
2.2       luotonen  289:     HTList_addObject(server->setups, (void*)setup);
2.1       luotonen  290: 
                    291:     return setup;
                    292: }
                    293: 
                    294: 
                    295: 
                    296: /* PRIVATE                                             HTAASetup_delete()
                    297: **                     FREE A HTAASetup STRUCTURE
                    298: ** ON ENTRY:
                    299: **     killme          is a pointer to the structure to free().
                    300: **
                    301: ** ON EXIT:
                    302: **     returns         nothing.
                    303: */
                    304: #ifdef NOT_NEEDED_IT_SEEMS
                    305: PRIVATE void HTAASetup_delete ARGS1(HTAASetup *, killme)
                    306: {
2.2       luotonen  307:     int scheme;
2.1       luotonen  308: 
                    309:     if (killme) {
2.2       luotonen  310:        if (killme->template) free(killme->template);
                    311:        if (killme->valid_schemes)
                    312:            HTList_delete(killme->valid_schemes);
                    313:        for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++)
                    314:            if (killme->scheme_specifics[scheme])
                    315:                HTAssocList_delete(killme->scheme_specifics[scheme]);
2.1       luotonen  316:        free(killme);
                    317:     }
                    318: }
                    319: #endif /*NOT_NEEDED_IT_SEEMS*/
                    320: 
                    321: 
                    322: 
                    323: /* PRIVATE                                     HTAASetup_updateSpecifics()
                    324: *              COPY SCHEME SPECIFIC PARAMETERS
                    325: **             TO HTAASetup STRUCTURE
                    326: ** ON ENTRY:
                    327: **     setup           destination setup structure.
                    328: **     specifics       string array containing scheme
                    329: **                     specific parameters for each scheme.
                    330: **                     If NULL, all the scheme specific
                    331: **                     parameters are set to NULL.
                    332: **
                    333: ** ON EXIT:
                    334: **     returns         nothing.
                    335: */
2.2       luotonen  336: PRIVATE void HTAASetup_updateSpecifics ARGS2(HTAASetup *,      setup,
                    337:                                             HTAssocList **,    specifics)
2.1       luotonen  338: {
2.2       luotonen  339:     int scheme;
2.1       luotonen  340: 
2.2       luotonen  341:     if (setup) {
                    342:        if (setup->scheme_specifics) {
                    343:            for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++) {
                    344:                if (setup->scheme_specifics[scheme])
                    345:                    HTAssocList_delete(setup->scheme_specifics[scheme]);
                    346:            }
                    347:            free(setup->scheme_specifics);
                    348:        }
                    349:        setup->scheme_specifics = specifics;
2.1       luotonen  350:     }
                    351: }
                    352: 
                    353: 
                    354: 
                    355: 
                    356: /*************************** HTAARealm **********************************/
                    357: 
                    358: /* PRIVATE                                             HTAARealm_lookup()
                    359: **             LOOKUP HTAARealm STRUCTURE BY REALM NAME
                    360: ** ON ENTRY:
2.4       luotonen  361: **     realm_table     a list of realm objects.
2.1       luotonen  362: **     realmname       is the name of realm to look for.
                    363: **
                    364: ** ON EXIT:
                    365: **     returns         the realm.  NULL, if not found.
                    366: */
2.4       luotonen  367: PRIVATE HTAARealm *HTAARealm_lookup ARGS2(HTList *,    realm_table,
                    368:                                          CONST char *, realmname)
2.1       luotonen  369: {
                    370:     if (realm_table && realmname) {
                    371:        HTList *cur = realm_table;
                    372:        HTAARealm *realm;
                    373:        
                    374:        while (NULL != (realm = (HTAARealm*)HTList_nextObject(cur))) {
                    375:            if (0==strcmp(realm->realmname, realmname))
                    376:                return realm;
                    377:        }
                    378:     }
                    379:     return NULL;       /* No table, NULL param, or not found */
                    380: }
                    381: 
                    382: 
                    383: 
                    384: /* PRIVATE                                             HTAARealm_new()
                    385: **             CREATE A NODE CONTAINING USERNAME AND
                    386: **             PASSWORD USED FOR THE GIVEN REALM.
                    387: **             IF REALM ALREADY EXISTS, CHANGE
                    388: **             USERNAME/PASSWORD.
                    389: ** ON ENTRY:
2.4       luotonen  390: **     realm_table     a list of realms to where to add
                    391: **                     the new one, too.
2.1       luotonen  392: **     realmname       is the name of the password domain.
                    393: **     username        and
                    394: **     password        are what you can expect them to be.
                    395: **
                    396: ** ON EXIT:
                    397: **     returns         the created realm.
                    398: */
2.4       luotonen  399: PRIVATE HTAARealm *HTAARealm_new ARGS4(HTList *,       realm_table,
                    400:                                       CONST char *,    realmname,
2.1       luotonen  401:                                       CONST char *,    username,
                    402:                                       CONST char *,    password)
                    403: {
                    404:     HTAARealm *realm;
                    405: 
2.4       luotonen  406:     realm = HTAARealm_lookup(realm_table, realmname);
2.1       luotonen  407: 
                    408:     if (!realm) {
                    409:        if (!(realm = (HTAARealm*)malloc(sizeof(HTAARealm))))
                    410:            outofmem(__FILE__, "HTAARealm_new");
                    411:        realm->realmname = NULL;
                    412:        realm->username = NULL;
                    413:        realm->password = NULL;
                    414:        StrAllocCopy(realm->realmname, realmname);
2.4       luotonen  415:        if (realm_table) HTList_addObject(realm_table, (void*)realm);
2.1       luotonen  416:     }
                    417:     if (username) StrAllocCopy(realm->username, username);
                    418:     if (password) StrAllocCopy(realm->password, password);
                    419: 
                    420:     return realm;
                    421: }
                    422: 
                    423: 
                    424: 
                    425: 
                    426: /***************** Basic and Pubkey Authentication ************************/
                    427: 
2.7       luotonen  428: /* PRIVATE                                             compose_Basic_auth()
2.1       luotonen  429: **
2.7       luotonen  430: **             COMPOSE Basic SCHEME AUTHENTICATION STRING
2.1       luotonen  431: **
                    432: ** ON ENTRY:
2.7       luotonen  433: **     req             request, where
                    434: **     req->scheme     == HTAA_BASIC
                    435: **     req->realm      contains username and password.
2.1       luotonen  436: **
                    437: ** ON EXIT:
                    438: **     returns         a newly composed authorization string,
2.5       luotonen  439: **                     NULL, if something fails.
2.1       luotonen  440: ** NOTE:
                    441: **     Like throughout the entire AA package, no string or structure
                    442: **     returned by AA package needs to (or should) be freed.
                    443: **
                    444: */
2.7       luotonen  445: PRIVATE char *compose_Basic_auth ARGS1(HTRequest *, req)
2.1       luotonen  446: {
                    447:     static char *result = NULL;        /* Uuencoded presentation, the result */
                    448:     char *cleartext = NULL;    /* Cleartext presentation */
                    449:     int len;
                    450: 
                    451:     FREE(result);      /* From previous call */
                    452: 
2.7       luotonen  453:     if (!req || req->scheme != HTAA_BASIC || !req->setup ||
                    454:        !req->setup->server)
2.5       luotonen  455:        return NULL;
2.1       luotonen  456: 
2.7       luotonen  457:     if (!req->realm) {
                    458:        char *realmname;
2.1       luotonen  459: 
2.7       luotonen  460:        if (!req->setup || !req->setup->scheme_specifics ||
                    461:            !(realmname =
                    462:              HTAssocList_lookup(req->setup->scheme_specifics[HTAA_BASIC],
                    463:                                 "realm")))
                    464:            return NULL;
                    465: 
                    466:        req->realm = HTAARealm_lookup(req->setup->server->realms, realmname);
                    467:        if (!req->realm) {
                    468:            req->realm = HTAARealm_new(req->setup->server->realms,
                    469:                                       realmname, NULL, NULL);
                    470:            return NULL;
2.1       luotonen  471:        }
                    472:     }
                    473: 
2.7       luotonen  474:     len = strlen(req->realm->username ? req->realm->username : "") +
                    475:          strlen(req->realm->password ? req->realm->password : "") + 3;
2.1       luotonen  476: 
2.5       luotonen  477:     if (!(cleartext  = (char*)calloc(len, 1)))
2.7       luotonen  478:        outofmem(__FILE__, "compose_Basic_auth");
2.1       luotonen  479: 
2.7       luotonen  480:     if (req->realm->username) strcpy(cleartext, req->realm->username);
2.3       luotonen  481:     else *cleartext = (char)0;
2.1       luotonen  482: 
                    483:     strcat(cleartext, ":");
                    484: 
2.7       luotonen  485:     if (req->realm->password) strcat(cleartext, req->realm->password);
                    486: 
                    487:     if (!(result = (char*)malloc(4 * ((len+2)/3) + 1)))
                    488:        outofmem(__FILE__, "compose_Basic_auth");
                    489:     HTUU_encode((unsigned char *)cleartext, strlen(cleartext), result);
                    490:     free(cleartext);
2.1       luotonen  491: 
                    492:     return result;
                    493: }
                    494: 
                    495: 
                    496: 
                    497: /* BROWSER PRIVATE                                     HTAA_selectScheme()
                    498: **             SELECT THE AUTHENTICATION SCHEME TO USE
                    499: ** ON ENTRY:
                    500: **     setup   is the server setup structure which can
                    501: **             be used to make the decision about the
                    502: **             used scheme.
                    503: **
                    504: **     When new authentication methods are added to library
                    505: **     this function makes the decision about which one to
                    506: **     use at a given time.  This can be done by inspecting
                    507: **     environment variables etc.
                    508: **
2.2       luotonen  509: **     Currently only searches for the first valid scheme,
                    510: **     and if nothing found suggests Basic scheme;
                    511: **
2.1       luotonen  512: ** ON EXIT:
                    513: **     returns the authentication scheme to use.
                    514: */
                    515: PRIVATE HTAAScheme HTAA_selectScheme ARGS1(HTAASetup *, setup)
                    516: {
2.2       luotonen  517:     HTAAScheme scheme;
                    518: 
                    519:     if (setup && setup->valid_schemes) {
                    520:        for (scheme=HTAA_BASIC; scheme < HTAA_MAX_SCHEMES; scheme++)
                    521:            if (-1 < HTList_indexOf(setup->valid_schemes, (void*)scheme))
                    522:                return scheme;
                    523:     }
2.7       luotonen  524:     return HTAA_NONE;
2.1       luotonen  525: }
                    526: 
                    527: 
                    528: 
                    529: 
                    530: /* BROWSER PUBLIC                                      HTAA_composeAuth()
                    531: **
2.7       luotonen  532: **     COMPOSE Authorization: HEADER LINE CONTENTS
2.1       luotonen  533: **     IF WE ALREADY KNOW THAT THE HOST REQUIRES AUTHENTICATION
                    534: **
                    535: ** ON ENTRY:
2.7       luotonen  536: **     req             request, which contains
                    537: **     req->setup      protection setup info on browser.
                    538: **     req->scheme     selected authentication scheme.
                    539: **     req->realm      for Basic scheme the username and password.
                    540: **
                    541: ** ON EXIT:
                    542: **     returns NO, if no authorization seems to be needed, and
                    543: **             req->authorization is NULL.
                    544: **             YES, if it has composed Authorization field,
                    545: **             in which case the result is in req->authorization,
                    546: **             e.g.
                    547: **
                    548: **                "Basic AkRDIhEF8sdEgs72F73bfaS=="
                    549: */
                    550: PUBLIC BOOL HTAA_composeAuth ARGS1(HTRequest *, req)
                    551: {
                    552:     char *auth_string = NULL;
                    553:     static char *docname;
                    554:     static char *hostname;
                    555:     int portnumber;
                    556:     char *colon;
                    557:     char *gate = NULL; /* Obsolite? */
2.9       luotonen  558:     char *arg = NULL;
2.7       luotonen  559: 
                    560:     FREE(hostname);    /* From previous call */
                    561:     FREE(docname);     /*      - " -         */
2.5       luotonen  562: 
2.9       luotonen  563:     if (!req  ||  !req->anchor)
2.7       luotonen  564:        return NO;
2.1       luotonen  565: 
2.10    ! luotonen  566: #ifdef OLD_CODE
2.8       luotonen  567:     if (req->authorization) {
2.9       luotonen  568:        CTRACE(stderr,
                    569: "HTAA_composeAuth: forwarding auth.info from client\nAuthorization: %s\n",
2.8       luotonen  570:               req->authorization);
                    571:        return YES;
                    572:     }
2.10    ! luotonen  573: #endif
2.8       luotonen  574: 
2.9       luotonen  575:     arg = HTAnchor_physical(req->anchor);
                    576:     docname = HTParse(arg, "", PARSE_PATH);
                    577:     hostname = HTParse((gate ? gate : arg), "", PARSE_HOST);
2.7       luotonen  578:     if (hostname &&
                    579:        NULL != (colon = strchr(hostname, ':'))) {
                    580:        *(colon++) = '\0';      /* Chop off port number */
                    581:        portnumber = atoi(colon);
                    582:     }
                    583:     else portnumber = 80;
                    584:        
                    585:     if (TRACE) fprintf(stderr,
                    586:                       "Composing Authorization for %s:%d/%s\n",
                    587:                       hostname, portnumber, docname);
2.1       luotonen  588: 
2.7       luotonen  589: #ifdef OLD_CODE
2.1       luotonen  590:     if (current_portnumber != portnumber ||
                    591:        !current_hostname || !current_docname ||
                    592:        !hostname         || !docname         ||
                    593:        0 != strcmp(current_hostname, hostname) ||
                    594:        0 != strcmp(current_docname, docname)) {
                    595: 
                    596:        retry = NO;
                    597: 
                    598:        current_portnumber = portnumber;
                    599:        
                    600:        if (hostname) StrAllocCopy(current_hostname, hostname);
                    601:        else FREE(current_hostname);
                    602: 
                    603:        if (docname) StrAllocCopy(current_docname, docname);
                    604:        else FREE(current_docname);
                    605:     }
                    606:     else retry = YES;
2.7       luotonen  607: #endif /*OLD_CODE*/
2.1       luotonen  608: 
2.7       luotonen  609:     if (!req->setup)
                    610:        req->setup = HTAASetup_lookup(hostname, portnumber, docname);
                    611:     if (!req->setup)
                    612:        return NO;
2.1       luotonen  613: 
2.7       luotonen  614:     if (req->scheme == HTAA_NONE)
                    615:        req->scheme = HTAA_selectScheme(req->setup);
2.1       luotonen  616: 
2.7       luotonen  617:     switch (req->scheme) {
2.1       luotonen  618:       case HTAA_BASIC:
2.7       luotonen  619:        auth_string = compose_Basic_auth(req);
                    620:        break;
2.1       luotonen  621:       case HTAA_PUBKEY:
                    622:       case HTAA_KERBEROS_V4:
                    623:        /* OTHER AUTHENTICATION ROUTINES ARE CALLED HERE */
                    624:       default:
                    625:        {
                    626:            char msg[100];
                    627:            sprintf(msg, "%s %s `%s'",
                    628:                    "This client doesn't know how to compose authentication",
2.7       luotonen  629:                    "information for scheme", HTAAScheme_name(req->scheme));
2.1       luotonen  630:            HTAlert(msg);
2.5       luotonen  631:            auth_string = NULL;
2.1       luotonen  632:        }
                    633:     } /* switch scheme */
                    634: 
2.7       luotonen  635:     req->setup->reprompt = NO;
2.1       luotonen  636: 
2.5       luotonen  637:     /* Added by marca. */
                    638:     if (!auth_string)
2.7       luotonen  639:        return NO;
2.5       luotonen  640:     
2.7       luotonen  641:     if (!(req->authorization =
                    642:          (char*)malloc(sizeof(char) * (strlen(auth_string)+40))))
2.1       luotonen  643:        outofmem(__FILE__, "HTAA_composeAuth");
                    644: 
2.7       luotonen  645:     strcpy(req->authorization, HTAAScheme_name(req->scheme));
                    646:     strcat(req->authorization, " ");
                    647:     strcat(req->authorization, auth_string);
2.1       luotonen  648: 
2.7       luotonen  649:     return YES;
                    650: }
2.1       luotonen  651: 
2.5       luotonen  652: 
2.7       luotonen  653: /* BROWSER OVERLOADED                                  HTPasswordDialog()
                    654: **
                    655: **             PROMPT USERNAME AND PASSWORD, AND MAKE A
                    656: **             CALLBACK TO FUNCTION HTLoadHTTP().
2.1       luotonen  657: **
2.7       luotonen  658: **     This function must be redifined by GUI clients, which
                    659: **     call HTLoadHTTP(req) when user presses "Ok".
2.1       luotonen  660: **
2.7       luotonen  661: ** ON ENTRY:
                    662: **     req             request.
                    663: **     req->dialog_msg prompting message.
                    664: **     req->setup      information about protections of this request.
                    665: **     req->realm      structure describing one password realm.
2.1       luotonen  666: **                     This function should only be called when
                    667: **                     server has replied with a 401 (Unauthorized)
2.7       luotonen  668: **                     status code, and req structure has been filled
                    669: **                     up according to server reply, especially the
                    670: **                     req->valid_shemes list must have been set up
                    671: **                     according to WWW-Authenticate: headers.
                    672: **     req->retry_callback
                    673: **                     function to call when username and password
                    674: **                     have been entered.
2.1       luotonen  675: ** ON EXIT:
2.7       luotonen  676: **
                    677: **     returns nothing.
                    678: **             Calls (*req->retry_callback)(req).
                    679: **
                    680: */
                    681: PUBLIC void HTPasswordDialog ARGS1(HTRequest *,        req)
2.1       luotonen  682: {
2.7       luotonen  683:     if (!req || !req->setup || !req->realm || !req->dialog_msg ||
                    684:        !req->retry_callback) {
                    685:        HTAlert("HTPasswordDialog() called with an illegal parameter");
                    686:        return;
                    687:     }
                    688:     if (req->setup->reprompt &&
                    689:        NO == HTConfirm("Authorization failed.  Retry?")) {
                    690:        return;
                    691:     } /* HTConfirm(...) == NO */
                    692:     else { /* re-ask username+password (if misspelled) */
                    693:        char *username = req->realm->username;
                    694:        char *password = NULL;
2.1       luotonen  695: 
2.7       luotonen  696:        HTPromptUsernameAndPassword(req->dialog_msg, &username, &password);
2.1       luotonen  697: 
2.7       luotonen  698:        if (req->realm->username) free(req->realm->username);
                    699:        if (req->realm->password) free(req->realm->password);
                    700:        req->realm->username = username;
                    701:        req->realm->password = password;
2.1       luotonen  702: 
2.7       luotonen  703:        if (!req->realm->username)
                    704:            return;             /* Suggested by marca; thanks! */
                    705:        else
                    706:            (*req->retry_callback)(req);        /* Callback */
                    707:     }
                    708: }
2.1       luotonen  709: 
                    710: 
                    711: 
2.7       luotonen  712: /* BROWSER PUBLIC                                      HTAA_retryWithAuth()
                    713: **
                    714: **             RETRY THE SERVER WITH AUTHORIZATION (OR IF
                    715: **             ALREADY RETRIED, WITH A DIFFERENT USERNAME
                    716: **             AND/OR PASSWORD (IF MISSPELLED)) OR CANCEL
                    717: ** ON ENTRY:
                    718: **     req             request.
                    719: **     req->valid_schemes
                    720: **                     This function should only be called when
                    721: **                     server has replied with a 401 (Unauthorized)
                    722: **                     status code, and req structure has been filled
                    723: **                     up according to server reply, especially the
                    724: **                     req->valid_shemes list must have been set up
                    725: **                     according to WWW-Authenticate: headers.
                    726: ** ON EXIT:
                    727: **     On GUI clients pops up a username/password dialog box
                    728: **     with "Ok" and "Cancel".
                    729: **     "Ok" button press should do a callback
                    730: **
                    731: **             HTLoadHTTP(req);
                    732: **
                    733: **     This actually done by function HTPasswordDialog(),
                    734: **     which GUI clients redefine.
                    735: **
                    736: **     returns         YES, if dialog box was popped up.
                    737: **                     NO, on failure.
                    738: */
                    739: PUBLIC BOOL HTAA_retryWithAuth ARGS2(HTRequest *,        req,
                    740:                                     HTRetryCallbackType, callback)
                    741: {
                    742:     int len;
                    743:     char *realmname;
2.9       luotonen  744:     char *arg = NULL;
2.1       luotonen  745: 
2.9       luotonen  746:     if (!req || !req->anchor ||
2.7       luotonen  747:        !req->valid_schemes || HTList_count(req->valid_schemes) == 0) {
                    748:        req->setup = NULL;
2.1       luotonen  749:        return NO;
                    750:     }
                    751: 
2.9       luotonen  752:     arg = HTAnchor_physical(req->anchor);
                    753: 
2.7       luotonen  754:     if (req->setup && req->setup->server) {
2.1       luotonen  755:        /* So we have already tried with authorization. */
                    756:        /* Either we don't have access or username or   */
                    757:        /* password was misspelled.                     */
                    758:            
                    759:        /* Update scheme-specific parameters    */
                    760:        /* (in case they have expired by chance).       */
2.7       luotonen  761:        HTAASetup_updateSpecifics(req->setup, req->scheme_specifics);
                    762:        req->scheme = HTAA_selectScheme(req->setup);
                    763:        req->setup->reprompt = YES;
                    764:     }
2.1       luotonen  765:     else { /* current_setup == NULL, i.e. we have a     */
                    766:           /* first connection to a protected server or  */
                    767:           /* the server serves a wider set of documents */
                    768:           /* than we expected so far.                   */
                    769: 
2.7       luotonen  770:        static char *hostname;
                    771:        static char *docname;
                    772:        int portnumber;
                    773:        char *colon;
                    774:        HTAAServer *server;
                    775: 
                    776:        FREE(hostname); /* From previous call */
                    777:        FREE(docname);  /*      - " -         */
                    778: 
2.9       luotonen  779:        docname = HTParse(arg, "", PARSE_PATH);
                    780:        hostname = HTParse(arg, "", PARSE_HOST);
2.7       luotonen  781:        if (hostname &&
                    782:            NULL != (colon = strchr(hostname, ':'))) {
                    783:            *(colon++) = '\0';  /* Chop off port number */
                    784:            portnumber = atoi(colon);
                    785:        }
                    786:        else portnumber = 80;
                    787:        
                    788:        if (TRACE) fprintf(stderr,
                    789:                           "HTAA_retryWithAuth: first retry of %s:%d/%s\n",
                    790:                           hostname, portnumber, docname);
                    791: 
                    792:        if (!(server = HTAAServer_lookup(hostname, portnumber))) {
                    793:            server = HTAAServer_new(hostname, portnumber);
                    794:        }
                    795:        else {
                    796:            HTAlert("Access without authorization denied -- retrying");
2.1       luotonen  797:        }
                    798: 
2.7       luotonen  799:        if (!req->prot_template)
                    800:            req->prot_template = HTAA_makeProtectionTemplate(docname);
                    801:        req->setup = HTAASetup_new(server, 
                    802:                                   req->prot_template,
                    803:                                   req->valid_schemes,
                    804:                                   req->scheme_specifics);
                    805:        req->setup->reprompt = NO;
                    806:        req->scheme = HTAA_selectScheme(req->setup);
                    807: 
2.1       luotonen  808:     } /* else current_setup == NULL */
                    809: 
2.7       luotonen  810:     realmname = HTAssocList_lookup(req->setup->scheme_specifics[req->scheme],
                    811:                                   "realm");
                    812:     if (!realmname)
                    813:        return NO;
                    814: 
                    815:     req->realm = HTAARealm_lookup(req->setup->server->realms, realmname);
                    816:     if (!req->realm)
                    817:        req->realm = HTAARealm_new(req->setup->server->realms,
                    818:                                   realmname, NULL, NULL);
                    819: 
                    820:     len = strlen(realmname) + 100;
                    821:     if (req->setup->server->hostname)
                    822:        len += strlen(req->setup->server->hostname);
                    823:     if (!(req->dialog_msg = (char*)malloc(len)))
                    824:        outofmem(__FILE__, "HTAA_retryWithAuth");
                    825:     if (!req->realm->username)
                    826:        sprintf(req->dialog_msg, "%s %s at %s",
                    827:                "Document is protected. Enter username for",
                    828:                req->realm->realmname,
                    829:                req->setup->server->hostname
                    830:                ? req->setup->server->hostname : "??");
                    831:     else sprintf(req->dialog_msg, "%s %s at %s",
                    832:                 "Authorization failed. Enter username for",
                    833:                 req->realm->realmname,
                    834:                 req->setup->server->hostname
                    835:                 ? req->setup->server->hostname : "??");
                    836: 
                    837:     req->retry_callback = callback;    /* Set callback function */
                    838:     HTPasswordDialog(req);
                    839:     return YES;
2.1       luotonen  840: }
2.7       luotonen  841: 
                    842: 
2.1       luotonen  843: 

Webmaster