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

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

Webmaster