Example #1
0
cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
{
    cm_cell_t *cp, *cp2;
    long code;
    char fullname[CELL_MAXNAMELEN]="";
    char linkedName[CELL_MAXNAMELEN]="";
    char name[CELL_MAXNAMELEN]="";
    int  hasWriteLock = 0;
    int  hasMutex = 0;
    afs_uint32 hash;
    cm_cell_rock_t rock;
    size_t len;

    if (namep == NULL || !namep[0] || !strcmp(namep,CM_IOCTL_FILENAME_NOSLASH))
        return NULL;

    /*
     * Strip off any trailing dots at the end of the cell name.
     * Failure to do so results in an undesireable alias as the
     * result of DNS AFSDB record lookups where a trailing dot
     * has special meaning.
     */
    strncpy(name, namep, CELL_MAXNAMELEN);
    for (len = strlen(namep); len > 0 && namep[len-1] == '.'; len--) {
        name[len-1] = '\0';
    }
    if (len == 0)
        return NULL;
    namep = name;

    hash = CM_CELL_NAME_HASH(namep);

    lock_ObtainRead(&cm_cellLock);
    for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) {
        if (cm_stricmp_utf8(namep, cp->name) == 0) {
            strncpy(fullname, cp->name, CELL_MAXNAMELEN);
            fullname[CELL_MAXNAMELEN-1] = '\0';
            break;
        }
    }

    if (!cp) {
        for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) {
            if (strnicmp(namep, cp->name, strlen(namep)) == 0) {
                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
                fullname[CELL_MAXNAMELEN-1] = '\0';
                break;
            }
        }
    }

    if (cp) {
        lock_ReleaseRead(&cm_cellLock);
        cm_UpdateCell(cp, flags);
    } else if (flags & CM_FLAG_CREATE) {
        lock_ConvertRToW(&cm_cellLock);
        hasWriteLock = 1;

        /* when we dropped the lock the cell could have been added
         * to the list so check again while holding the write lock
         */
        for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) {
            if (cm_stricmp_utf8(namep, cp->name) == 0) {
                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
                fullname[CELL_MAXNAMELEN-1] = '\0';
                break;
            }
        }

        if (cp)
            goto done;

        for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) {
            if (strnicmp(namep, cp->name, strlen(namep)) == 0) {
                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
                fullname[CELL_MAXNAMELEN-1] = '\0';
                break;
            }
        }

        if (cp) {
            lock_ReleaseWrite(&cm_cellLock);
            lock_ObtainMutex(&cp->mx);
            lock_ObtainWrite(&cm_cellLock);
            cm_AddCellToNameHashTable(cp);
            cm_AddCellToIDHashTable(cp);
            lock_ReleaseMutex(&cp->mx);
            goto done;
        }

        if ( cm_data.freeCellsp != NULL ) {
            cp = cm_data.freeCellsp;
            cm_data.freeCellsp = cp->freeNextp;

            /*
             * The magic, cellID, and mx fields are already set.
             */
        } else {
            if ( cm_data.currentCells >= cm_data.maxCells )
                osi_panic("Exceeded Max Cells", __FILE__, __LINE__);

            /* don't increment currentCells until we know that we
             * are going to keep this entry
             */
            cp = &cm_data.cellBaseAddress[cm_data.currentCells];
            memset(cp, 0, sizeof(cm_cell_t));
            cp->magic = CM_CELL_MAGIC;

            /* the cellID cannot be 0 */
            cp->cellID = ++cm_data.currentCells;

            /* otherwise we found the cell, and so we're nearly done */
            lock_InitializeMutex(&cp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);
        }

        lock_ReleaseWrite(&cm_cellLock);
        hasWriteLock = 0;

        rock.cellp = cp;
        rock.flags = flags;
        code = cm_SearchCellRegistry(1, namep, fullname, linkedName, cm_AddCellProc, &rock);
        if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
            code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock);
        if (code) {
            osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s",
                      osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname),
                      osi_LogSaveString(afsd_logp,linkedName));

            if (cm_dnsEnabled) {
                int ttl;

                code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, &rock);
                if ( code ) {
                    osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s",
                             osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname));
                    lock_ObtainMutex(&cp->mx);
                    lock_ObtainWrite(&cm_cellLock);
                    hasWriteLock = 1;
                    cm_RemoveCellFromIDHashTable(cp);
                    cm_RemoveCellFromNameHashTable(cp);
                    lock_ReleaseMutex(&cp->mx);
                    cm_FreeCell(cp);
                    cp = NULL;
                    goto done;
                } else {   /* got cell from DNS */
                    lock_ObtainMutex(&cp->mx);
                    hasMutex = 1;
                    _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS);
                    _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID);
                    cp->timeout = time(0) + ttl;
                }
            }
            else
            {
                lock_ObtainMutex(&cp->mx);
                lock_ObtainWrite(&cm_cellLock);
                hasWriteLock = 1;
                cm_RemoveCellFromIDHashTable(cp);
                cm_RemoveCellFromNameHashTable(cp);
                lock_ReleaseMutex(&cp->mx);
                cm_FreeCell(cp);
                cp = NULL;
                goto done;
	    }
        } else {
            lock_ObtainMutex(&cp->mx);
            hasMutex = 1;
	    cp->timeout = time(0) + 7200;	/* two hour timeout */
	}

        /* we have now been given the fullname of the cell.  It may
         * be that we already have a cell with that name.  If so,
         * we should use it instead of completing the allocation
         * of a new cm_cell_t
         */
        lock_ObtainRead(&cm_cellLock);
        hash = CM_CELL_NAME_HASH(fullname);
        for (cp2 = cm_data.cellNameHashTablep[hash]; cp2; cp2=cp2->nameNextp) {
            if (cm_stricmp_utf8(fullname, cp2->name) == 0) {
                break;
            }
        }

        if (cp2) {
            if (!hasMutex) {
                lock_ObtainMutex(&cp->mx);
                hasMutex = 1;
            }
            lock_ConvertRToW(&cm_cellLock);
            hasWriteLock = 1;
            cm_RemoveCellFromIDHashTable(cp);
            cm_RemoveCellFromNameHashTable(cp);
            lock_ReleaseMutex(&cp->mx);
            hasMutex = 0;
            cm_FreeCell(cp);
            cp = cp2;
            goto done;
        }
        lock_ReleaseRead(&cm_cellLock);

        /* randomise among those vlservers having the same rank*/
        cm_RandomizeServer(&cp->vlServersp);

        if (!hasMutex)
            lock_ObtainMutex(&cp->mx);

        /* copy in name */
        strncpy(cp->name, fullname, CELL_MAXNAMELEN);
        cp->name[CELL_MAXNAMELEN-1] = '\0';

        strncpy(cp->linkedName, linkedName, CELL_MAXNAMELEN);
        cp->linkedName[CELL_MAXNAMELEN-1] = '\0';

        lock_ObtainWrite(&cm_cellLock);
        hasWriteLock = 1;
        cm_AddCellToNameHashTable(cp);
        cm_AddCellToIDHashTable(cp);
        lock_ReleaseMutex(&cp->mx);
        hasMutex = 0;

        /* append cell to global list */
        if (cm_data.allCellsp == NULL) {
            cm_data.allCellsp = cp;
        } else {
            for (cp2 = cm_data.allCellsp; cp2->allNextp; cp2=cp2->allNextp)
                ;
            cp2->allNextp = cp;
        }
        cp->allNextp = NULL;

    } else {
        lock_ReleaseRead(&cm_cellLock);
    }
  done:
    if (hasMutex && cp)
        lock_ReleaseMutex(&cp->mx);
    if (hasWriteLock)
        lock_ReleaseWrite(&cm_cellLock);

    /* fullname is not valid if cp == NULL */
    if (newnamep) {
        if (cp) {
            strncpy(newnamep, fullname, CELL_MAXNAMELEN);
            newnamep[CELL_MAXNAMELEN-1]='\0';
        } else {
            newnamep[0] = '\0';
        }
    }

    if (cp && cp->linkedName[0]) {
        cm_cell_t * linkedCellp = NULL;

        if (!strcmp(cp->name, cp->linkedName)) {
            cp->linkedName[0] = '\0';
        } else if (!(flags & CM_FLAG_NOMOUNTCHASE)) {
            linkedCellp = cm_GetCell(cp->linkedName, CM_FLAG_CREATE|CM_FLAG_NOPROBE|CM_FLAG_NOMOUNTCHASE);

            lock_ObtainWrite(&cm_cellLock);
            if (!linkedCellp ||
                (linkedCellp->linkedName[0] && strcmp(cp->name, linkedCellp->linkedName))) {
                cp->linkedName[0] = '\0';
            } else {
                strncpy(linkedCellp->linkedName, cp->name, CELL_MAXNAMELEN);
                linkedCellp->linkedName[CELL_MAXNAMELEN-1]='\0';
            }
            lock_ReleaseWrite(&cm_cellLock);
        }
    }
    return cp;
}
Example #2
0
long cm_SearchCellFileEx(char *cellNamep, char *newCellNamep,
                         char *linkedNamep,
                         cm_configProc_t *procp, void *rockp)
{
    char wdir[MAX_PATH]="";
    FILE *tfilep = NULL, *bestp, *tempp;
    char *tp, *linkp;
    char lineBuffer[257];
    struct hostent *thp;
    char *valuep;
    struct sockaddr_in vlSockAddr;
    int inRightCell = 0;
    int foundCell = 0;
    long code;
    int tracking = 1, partial = 0;
    size_t len;

    if ( IsWindowsModule(cellNamep) )
	return -3;

    cm_GetCellServDB(wdir, sizeof(wdir));
    if (*wdir)
        tfilep = fopen(wdir, "r");

    if (!tfilep) 
        return -2;

    bestp = fopen(wdir, "r");
    
#ifdef CELLSERV_DEBUG
    osi_Log2(afsd_logp,"cm_searchfile fopen handle[%p], wdir[%s]", bestp, 
	     osi_LogSaveString(afsd_logp,wdir));
#endif
    /* have we seen the cell line for the guy we're looking for? */
    while (1) {
        linkp = NULL;
        tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep);
        if (tracking)
	    (void) fgets(lineBuffer, sizeof(lineBuffer), bestp);
        if (tp == NULL) {
	    if (feof(tfilep)) {
		/* hit EOF */
		if (partial) {
		    /*
		     * found partial match earlier;
		     * now go back to it
		     */
		    tempp = bestp;
		    bestp = tfilep;
		    tfilep = tempp;
		    inRightCell = 1;
		    partial = 0;
		    continue;
		}
		else {
		    fclose(tfilep);
		    fclose(bestp);
		    return (foundCell? 0 : -3);
		}
	    }
        }	

        /* turn trailing cr or lf into null */
        tp = strrchr(lineBuffer, '\r');
        if (tp) *tp = 0;
        tp = strrchr(lineBuffer, '\n');
        if (tp) *tp = 0;

	/* skip blank lines */
        if (lineBuffer[0] == 0) continue;

        /*
         * The format is:
         *   >[cell] [linked-cell] #[Description]
         * where linked-cell and Description are optional
         */
        if (lineBuffer[0] == '>') {
            if (inRightCell) {
                fclose(tfilep);
                fclose(bestp);
                return(foundCell ? 0 : -6);
            }

            /* 
             * terminate the cellname at the first white space
             * leaving 'tp' pointing to the next string if any
             */
            for (tp = &lineBuffer[1]; tp && !isspace(*tp); tp++);
            if (tp) {
                *tp = '\0';
                for (tp++ ;tp && isspace(*tp); tp++);
                if (*tp != '#') {
                    linkp = tp;
                    for (; tp && !isspace(*tp); tp++);
                    if (tp) 
                        *tp = '\0';
                }
            }

	    /* now see if this is the right cell */
            if (stricmp(lineBuffer+1, cellNamep) == 0) {
		/* found the cell we're looking for */
		if (newCellNamep) {
                    if (FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, lineBuffer+1))) {
                        fclose(tfilep);
                        fclose(bestp);
                        return(-1);
                    }
                    strlwr(newCellNamep);
                }
                if (linkedNamep) {
                    if (FAILED(StringCchCopy(linkedNamep, CELL_MAXNAMELEN, linkp ? linkp : ""))) {
                        fclose(tfilep);
                        fclose(bestp);
                        return(-1);
                    }
                    strlwr(linkedNamep);
                }
                inRightCell = 1;
		tracking = 0;
#ifdef CELLSERV_DEBUG                
		osi_Log2(afsd_logp, "cm_searchfile is cell inRightCell[%p], linebuffer[%s]",
			 inRightCell, osi_LogSaveString(afsd_logp,lineBuffer));
#endif
	    }
	    else if (cm_stricmp_utf8(lineBuffer+1, cellNamep) == 0) {
		/* partial match */
		if (partial) {	/* ambiguous */
		    fclose(tfilep);
		    fclose(bestp);
		    return -5;
		}
		if (newCellNamep) {
                    if (FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, lineBuffer+1))) {
                        fclose(tfilep);
                        fclose(bestp);
                        return(-1);
                    }
                    strlwr(newCellNamep);
                }
                if (linkedNamep) {
                    if (FAILED(StringCchCopy(linkedNamep, CELL_MAXNAMELEN, linkp ? linkp : ""))) {
                        fclose(tfilep);
                        fclose(bestp);
                        return(-1);
                    }
                    strlwr(linkedNamep);
                }
		inRightCell = 0;
		tracking = 0;
		partial = 1;
	    }
            else inRightCell = 0;
        }
        else {
            valuep = strchr(lineBuffer, '#');
	    if (valuep == NULL) {
		fclose(tfilep);
		fclose(bestp);
		return -4;
	    }
            valuep++;	/* skip the "#" */

            valuep += strspn(valuep, " \t"); /* skip SP & TAB */
            /*
             * strip spaces and tabs in the end. They should not be there according to CellServDB format
             * so do this just in case
	     */
            if(FAILED(StringCchLength(valuep, sizeof(lineBuffer), &len))) {
                fclose(tfilep);
                fclose(bestp);
                return(-1);
            } else {
                len--;
                while(isspace(valuep[len]))
                    valuep[len--] = '\0';
                while(isspace(*valuep))
                    valuep++;
            }

	    if (inRightCell) {
                char hostname[256];
                int  i, isClone = 0;

                isClone = (lineBuffer[0] == '[');

                /* copy just the first word and ignore trailing white space */
                for ( i=0; valuep[i] && !isspace(valuep[i]) && i<sizeof(hostname); i++)
                    hostname[i] = valuep[i];
                hostname[i] = '\0';

		/* add the server to the VLDB list */
                WSASetLastError(0);
                thp = gethostbyname(hostname);
#ifdef CELLSERV_DEBUG
		osi_Log3(afsd_logp,"cm_searchfile inRightCell thp[%p], valuep[%s], WSAGetLastError[%d]",
			 thp, osi_LogSaveString(afsd_logp,hostname), WSAGetLastError());
#endif
		if (thp) {
                    int foundAddr = 0;
                    for (i=0 ; thp->h_addr_list[i]; i++) {
                        if (thp->h_addrtype != AF_INET)
                            continue;
                        memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr_list[i],
                               sizeof(long));
                        vlSockAddr.sin_port = htons(7003);
                        vlSockAddr.sin_family = AF_INET;
                        /* sin_port supplied by connection code */
                        if (procp)
                            (*procp)(rockp, &vlSockAddr, hostname, 0);
                        foundAddr = 1;
                    }
                    /* if we didn't find a valid address, force the use of the specified one */
                    if (!foundAddr)
                        thp = NULL;
		}
                if (!thp) {
                    afs_uint32 ip_addr;
		    unsigned int c1, c2, c3, c4;
                    
                    /* Since there is no gethostbyname() data 
		     * available we will read the IP address
		     * stored in the CellServDB file
                     */
                    if (isClone)
                        code = sscanf(lineBuffer, "[%u.%u.%u.%u]",
                                      &c1, &c2, &c3, &c4);
                    else
                        code = sscanf(lineBuffer, " %u.%u.%u.%u",
                                      &c1, &c2, &c3, &c4);
                    if (code == 4 && c1<256 && c2<256 && c3<256 && c4<256) {
                        tp = (unsigned char *) &ip_addr;
                        *tp++ = c1;
                        *tp++ = c2;
                        *tp++ = c3;
                        *tp++ = c4;
                        memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
                                sizeof(long));
                        vlSockAddr.sin_port = htons(7003);
                        vlSockAddr.sin_family = AF_INET;
                        /* sin_port supplied by connection code */
                        if (procp)
                            (*procp)(rockp, &vlSockAddr, hostname, 0);
                    }
                }
                foundCell = 1;
            }
        }	/* a vldb line */
    }		/* while loop processing all lines */

    /* if for some unknown reason cell is not found, return negative code (-11) ??? */
    return (foundCell) ? 0 : -11;
}
Example #3
0
int getAFSServer(const char *service, const char *protocol, const char *cellName,
                 unsigned short afsdbPort,  /* network byte order */
                 int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
                 unsigned short ports[],    /* network byte order */
                 unsigned short ipRanks[],
                 int *numServers, int *ttl)
{
#ifndef DNSAPI_ENV
    SOCKET commSock;
    SOCKADDR_IN sockAddr;
    PDNS_HDR  pDNShdr;
    char buffer[BUFSIZE];
    char query[1024];
    int rc;

#ifdef DEBUG
    fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
#endif

    *numServers = 0;
    *ttl = 0;

#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
    if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
        cm_InitDNS(1);         /* assume enabled */
    }
#endif
    if (cm_dnsEnabled == 0) {  /* possibly we failed in cm_InitDNS above */
        fprintf(stderr, "DNS initialization failed, disabled\n");
        return -1;
    }
  
    if (service == NULL || protocol == NULL || cellName == NULL) {
        fprintf(stderr, "invalid input\n");
        return -1;
    }

    sockAddr = setSockAddr(dns_addr, DNS_PORT);
  
    commSock = socket( AF_INET, SOCK_DGRAM, 0 );
    if ( commSock < 0 )
    {
        /*afsi_log("socket() failed\n");*/
        fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
        return (-1);
    } 

    StringCbCopyA(query, sizeof(query), cellName);
    if (query[strlen(query)-1] != '.') {
        StringCbCatA(query, sizeof(query), ".");
    }

    rc = send_DNS_AFSDB_Query(query,commSock,sockAddr, buffer);
    if (rc < 0) {
        closesocket(commSock);
        fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
        return -1;
    }
    
    pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
  
    /*printReplyBuffer_AFSDB(pDNShdr);*/
    if (pDNShdr)
        processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, ports, ipRanks, numServers, ttl);

    closesocket(commSock);
    if (*numServers == 0)
        return(-1);
    else
        return 0;
#else /* DNSAPI_ENV */
    PDNS_RECORD pDnsCell, pDnsIter, pDnsVol, pDnsVolIter, pDnsCIter;
    int i;
    char query[1024];

    *numServers = 0;
    *ttl = 0;

    if (service == NULL || protocol == NULL || cellName == NULL)
        return -1;

#ifdef AFS_FREELANCE_CLIENT
    if ( cm_stricmp_utf8N(cellName, "Freelance.Local.Root") == 0 )
        return -1;
#endif /* AFS_FREELANCE_CLIENT */

    /* query the SRV _afs3-vlserver._udp records of cell */
    StringCbPrintf(query, sizeof(query), "_%s._%s.%s", service, protocol, cellName);
    if (query[strlen(query)-1] != '.') {
        StringCbCatA(query, sizeof(query), ".");
    }

    if (DnsQuery_A(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
        /* go through the returned records */
        for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
            /* if we find an SRV record, we found the service */
            if (pDnsIter->wType == DNS_TYPE_SRV) {
                StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
                              pDnsIter->Data.SRV.pNameTarget);
                ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
                ports[*numServers] = htons(pDnsIter->Data.SRV.wPort);
                (*numServers)++;

                if (!*ttl) 
                    *ttl = pDnsIter->dwTtl;
                if (*numServers == AFSMAXCELLHOSTS) 
                    break;
            }
        }

        for (i=0;i<*numServers;i++) 
            cellHostAddrs[i] = 0;

        /* now check if there are any A records in the results */
        for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
            if(pDnsIter->wType == DNS_TYPE_A)
                /* check if its for one of the service */
                for (i=0;i<*numServers;i++)
                    if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
                        cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
        }

        for (i=0;i<*numServers;i++) {
            /* if we don't have an IP yet, then we should try resolving the afs3-vlserver hostname
            in a separate query. */
            if (!cellHostAddrs[i]) {
                if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
                    for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
                        /* if we get an A record, keep it */
                        if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
                            cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
                            break;
                        }
                        /* if we get a CNAME, look for a corresponding A record */
                        if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
                            for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
                                if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
                                    cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
                                    break;
                                }
                            }
                            if (cellHostAddrs[i]) 
                                break;
                            /* TODO: if the additional section is missing, then do another lookup for the CNAME */
                        }
                    }
                    /* we are done with the service lookup */
                    DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
                }
            }
        }
        DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
    }
    else {
        /* query the AFSDB records of cell */
        StringCbCopyA(query, sizeof(query), cellName);
        if (query[strlen(query)-1] != '.') {
            StringCbCatA(query, sizeof(query), ".");
        }

        if (DnsQuery_A(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &pDnsCell, NULL) == ERROR_SUCCESS) {
            /* go through the returned records */
            for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
                /* if we find an AFSDB record with Preference set to 1, we found a service instance */
                if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
                    StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
                                   pDnsIter->Data.Afsdb.pNameExchange);
                    ipRanks[*numServers] = 0;
                    ports[*numServers] = afsdbPort;
                    (*numServers)++;

                    if (!*ttl) 
                        *ttl = pDnsIter->dwTtl;
                    if (*numServers == AFSMAXCELLHOSTS) 
                        break;
                }
            }

            for (i=0;i<*numServers;i++) 
                cellHostAddrs[i] = 0;

            /* now check if there are any A records in the results */
            for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
                if(pDnsIter->wType == DNS_TYPE_A)
                    /* check if its for one of the service */
                    for (i=0;i<*numServers;i++)
                        if(cm_stricmp_utf8(pDnsIter->pName, cellHostNames[i]) == 0)
                            cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
            }

            for (i=0;i<*numServers;i++) {
                /* if we don't have an IP yet, then we should try resolving the service hostname
                in a separate query. */
                if (!cellHostAddrs[i]) {
                    if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
                        for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
                            /* if we get an A record, keep it */
                            if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
                                cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
                                break;
                            }
                            /* if we get a CNAME, look for a corresponding A record */
                            if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
                                for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
                                    if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
                                        cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
                                        break;
                                    }
                                }
                                if (cellHostAddrs[i]) 
                                    break;
                                /* TODO: if the additional section is missing, then do another lookup for the CNAME */
                            }
                        }
                        /* we are done with the service lookup */
                        DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
                    }
                }
            }
            DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
        }
    }

    if ( *numServers > 0 )
        return 0;
    else        
        return -1;
#endif /* DNSAPI_ENV */
}
Example #4
0
BOOL
afsd_ServicePerformFlushVolumes()
{
    CONST CHAR	COLON = ':';
    CONST CHAR	SLASH = '\\';
    CONST DWORD	NETRESBUFSIZE = 16384;
    CHAR	bufMessage[1024];
    UINT	i;
    DWORD	dwServerSize;
    DWORD	dwRet;
    DWORD	dwCount;
    DWORD	dwNetResBufSize;
    DWORD	dwTotalVols = 0;
    DWORD	dwVolBegin, dwVolEnd;
    DWORD	dwFlushBegin, dwFlushEnd;
    HANDLE	hEnum;
    LPNETRESOURCE	lpNetResBuf, lpnr;
    char        *pszShareName, *pc;
    afs_int32	afsRet = 0;

    if (cm_noIPAddr == 0) {
        // Nothing to do if we only have a loopback interface
        return TRUE;
    }

    // Determine the root share name (\\AFS\ALL or \\<machine>-AFS\ALL),
    // and the length of the server name prefix.
    pszShareName = smb_GetSharename();
    if (pszShareName == NULL)
    {
        LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_SHARE_NAME, NULL);
        return FALSE;
    }
    pc = strrchr(pszShareName, SLASH);
    if ((pc == NULL) || ((dwServerSize = (DWORD)(pc - pszShareName)) < 3))
    {
        LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_BAD_SHARE_NAME,
                  pszShareName, NULL);
        free(pszShareName);
        return FALSE;
    }

    // Allocate a buffer to hold network resources returned by
    // WNetEnumResource().
    lpNetResBuf = malloc(NETRESBUFSIZE);
    if (lpNetResBuf == NULL)
    {
        // Out of memory, give up now.
        LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_MEMORY, NULL);
        free(pszShareName);
        return FALSE;
    }

    // Initialize the flush timer.  Note that GetTickCount() returns
    // the number of milliseconds since the system started, in a DWORD,
    // so that the value wraps around every 49.7 days.  We do not bother
    // to handle the case where the flush elapsed time is greater than
    // that.
    dwFlushBegin = GetTickCount();

    dwRet = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL,
                          &hEnum);
    if (dwRet != NO_ERROR)
    {
        LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_OPEN_ENUM_ERROR,
                         dwRet);
        free(pszShareName);
        return FALSE;
    }

    // Loop to enumerate network resources, and flush those associated
    // with AFS volumes.
    while (1)
    {
        dwCount = -1;
        memset(lpNetResBuf, 0, NETRESBUFSIZE);
        dwNetResBufSize = NETRESBUFSIZE;
        dwRet = WNetEnumResource(hEnum, &dwCount,
                                  lpNetResBuf, &dwNetResBufSize);
        if (dwRet != NO_ERROR)
            break;
        // Iterate over the returned network resources.
        for (i = 0, lpnr = lpNetResBuf; i < dwCount; i++, lpnr++)
        {
            // Ensure resource has a remote name, and is connected.
            if ((lpnr->lpRemoteName == NULL) ||
                 (lpnr->dwScope != RESOURCE_CONNECTED))
                continue;
            if ((_strnicmp(lpnr->lpRemoteName, pszShareName,
                            dwServerSize) == 0) &&
                 (lpnr->lpRemoteName[dwServerSize] == SLASH))
            {
                // got one!
                // but we don't want to flush '\\[...]afs\all'
                if (cm_stricmp_utf8(lpnr->lpRemoteName, pszShareName) == 0)
                    continue;
                ++dwTotalVols;

                dwVolBegin = GetTickCount();
                afsRet = afsd_ServicePerformFlushVolumeCmd(lpnr->lpRemoteName);
                dwVolEnd = GetTickCount();
                if (afsRet == 0)
                {
                    LogTimingEvent(MSG_TIME_FLUSH_PER_VOLUME,
                                    lpnr->lpRemoteName,
                                    dwVolEnd - dwVolBegin);
                }
                else
                {
                    LogEvent(EVENTLOG_WARNING_TYPE,
                              MSG_FLUSH_FAILED,
                              lpnr->lpRemoteName, NULL);
                }
            }
        }
    }
    WNetCloseEnum(hEnum);
    free(lpNetResBuf);
    free(pszShareName);
    if (dwRet != ERROR_NO_MORE_ITEMS)
    {
        LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_ENUM_ERROR,
                         dwRet);
        return FALSE;
    }

    dwFlushEnd = GetTickCount();

    // display total volume count in Event Logger
    sprintf(bufMessage, "%d", dwTotalVols);
    LogTimingEvent(MSG_TIME_FLUSH_TOTAL, bufMessage,
                    dwFlushEnd - dwFlushBegin);

    return TRUE;
}
Example #5
0
DWORD APIENTRY NPLogonNotify(
	PLUID lpLogonId,
	LPCWSTR lpAuthentInfoType,
	LPVOID lpAuthentInfo,
	LPCWSTR lpPreviousAuthentInfoType,
	LPVOID lpPreviousAuthentInfo,
	LPWSTR lpStationName,
	LPVOID StationHandle,
	LPWSTR *lpLogonScript)
{
    char uname[MAX_USERNAME_LENGTH]="";
    char password[MAX_PASSWORD_LENGTH]="";
    char logonDomain[MAX_DOMAIN_LENGTH]="";
    char cell[256]="<non-integrated logon>";
    char homePath[MAX_PATH]="";
    char szLogonId[128] = "";

    MSV1_0_INTERACTIVE_LOGON *IL;

    DWORD code = 0, code2;

    int pw_exp;
    char *reason;
    char *ctemp;

    BOOLEAN interactive;
    BOOLEAN flag;
    DWORD LSPtype, LSPsize;
    HKEY NPKey;

    HWND hwndOwner = (HWND)StationHandle;

    BOOLEAN afsWillAutoStart;

    BOOLEAN lowercased_name = TRUE;

    LogonOptions_t opt; /* domain specific logon options */
    int retryInterval;
    int sleepInterval;

    /* Are we interactive? */
    interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);

#ifdef DISABLE_NON_INTERACTIVE
    /* Do not do anything if the logon session is not interactive. */
    if (!interactive)
	return 0;
#endif

    (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                         0, KEY_QUERY_VALUE, &NPKey);
    LSPsize=sizeof(TraceOption);
    RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
                     &LSPtype, (LPBYTE)&TraceOption, &LSPsize);

    RegCloseKey (NPKey);

    DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);

    /* Make sure the AFS Libraries are initialized */
    AfsLogonInit();

    /* Initialize Logon Script to none */
    *lpLogonScript=NULL;
    
    /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
     * our purposes */

    if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") && 
         wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
    {
        DebugEvent("Unsupported Authentication Info Type: %S",
                   lpAuthentInfoType);
        return 0;
    }

    IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;

    /* Convert from Unicode to ANSI */

    /*TODO: Use SecureZeroMemory to erase passwords */
    if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
	 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
	 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
 	return 0;

    /* Make sure AD-DOMANS sent from login that is sent to us is striped */
    ctemp = strchr(uname, '@');
    if (ctemp) *ctemp = 0;

    /* is the name all lowercase? */
    for ( ctemp = uname; *ctemp ; ctemp++) {
        if ( !islower(*ctemp) ) {
            lowercased_name = FALSE;
            break;
        }
    }

    /*
     * Get Logon options
     */

    GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
    retryInterval = opt.retryInterval;
    sleepInterval = opt.sleepInterval;
    *lpLogonScript = opt.logonScript;

    if (retryInterval < sleepInterval)
        sleepInterval = retryInterval;

    DebugEvent("Got logon script: %S",opt.logonScript);

    afsWillAutoStart = AFSWillAutoStart();

    DebugEvent("LogonOption[%x], Service AutoStart[%d]",
                opt.LogonOption,afsWillAutoStart);
    
    /* Check for zero length password if integrated logon*/
    if ( ISLOGONINTEGRATED(opt.LogonOption) )  {
        if ( password[0] == 0 ) {
            DebugEvent0("Password is the empty string");
            code = GT_PW_NULL;
            reason = "zero length password is illegal";
            code=0;
        }

        /* Get cell name if doing integrated logon.  
           We might overwrite this if we are logging into an AD realm and we find out that
           the user's home dir is in some other cell. */
        DebugEvent("About to call cm_GetRootCellName(%s)",cell);
        code = cm_GetRootCellName(cell);
        if (code < 0) { 
            DebugEvent0("Unable to obtain Root Cell");
            code = KTC_NOCELL;
            reason = "unknown cell";
            code=0;
        } else {
            DebugEvent("Cell is %s",cell);
        }       

        /* We get the user's home directory path, if applicable, though we can't lookup the
           cell right away because the client service may not have started yet. This call
           also sets the AD_REALM flag in opt.flags if applicable. */
        if (ISREMOTE(opt.flags)) {
            DebugEvent0("Is Remote");
            GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
        }
    }

    /* loop until AFS is started. */
    if (afsWillAutoStart) {
	while (IsServiceRunning() || IsServiceStartPending()) {
	    DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
			opt.LogonOption,afsWillAutoStart);

	    if (ISADREALM(opt.flags)) {
		code = GetFileCellName(homePath,cell,256);
		if (!code) {
		    DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
		}
		/* Don't bail out if GetFileCellName failed.
		 * The home dir may not be in AFS after all. 
		 */
	    } else
		code=0;
		
	    /* if Integrated Logon  */
	    if (ISLOGONINTEGRATED(opt.LogonOption))
	    {			
		if ( KFW_is_available() ) {
		    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
                    if (opt.realm) {
			char * principal, *p;
			size_t len, tlen;

			StringCchLength(opt.realm, MAX_DOMAIN_LENGTH, &tlen);
			len = tlen;
			StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
			len += tlen + 2;

			/* tlen is now the length of uname in characters */
			principal = (char *)malloc(len * sizeof(char));
			if ( principal ) {
			    StringCchCopy(principal, len, uname);
			    p = principal + tlen;
			    *p++ = '@';
                            StringCchCopy(p, len - tlen -1, opt.realm);
                            code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
                            DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
					    principal,opt.smbName,cell,code);
			    free(principal);
			}
                    } else {
                        code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
                        DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
                                    uname,opt.smbName,cell,code);
                    }
		    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
		    if (code == 0 && opt.theseCells) { 
			char * principal, *p;
			size_t len, tlen;

			StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
			len = tlen;
			StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
			len += tlen + 2;

			/* tlen is now the length of uname in characters */
			principal = (char *)malloc(len * sizeof(char));
			if ( principal ) {
			    StringCchCopy(principal, len, uname);
			    p = principal + tlen;
			    *p++ = '@';
                            if (opt.realm) {
                                StringCchCopy(p, len - tlen -1, opt.realm);
                            } else {
                                StringCchCopy(p, len - tlen - 1, cell);
                                for ( ;*p; p++) {
                                    *p = toupper(*p);
                                }
                            }
			    p = opt.theseCells;
			    while ( *p ) {
                                if ( cm_stricmp_utf8(p, cell) ) {
                                    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
                                    code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
                                    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
                                    DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
                                               principal,opt.smbName,p,code2);
                                }
				p += strlen(p) + 1;
			    }
			    free(principal);
			}
		    }
		} else {
		    code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
							uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
							&reason);
		    DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
				code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
		}       
		if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
		    for ( ctemp = uname; *ctemp ; ctemp++) {
			*ctemp = tolower(*ctemp);
		    }
		    lowercased_name = TRUE;
		    goto sleeping;
		}

		/* is service started yet?*/

		/* If we've failed because the client isn't running yet and the
		 * client is set to autostart (and therefore it makes sense for
		 * us to wait for it to start) then sleep a while and try again. 
		 * If the error was something else, then give up. */
		if (code != KTC_NOCM && code != KTC_NOCMRPC)
		    break;
	    }
	    else {  
		/*JUST check to see if its running*/
		if (IsServiceRunning())
		    break;
		if (!IsServiceStartPending()) {
		    code = KTC_NOCMRPC;
		    reason = "AFS Service start failed";
		    break;
		}
	    }

	    /* If the retry interval has expired and we still aren't
	     * logged in, then just give up if we are not in interactive
	     * mode or the failSilently flag is set, otherwise let the
	     * user know we failed and give them a chance to try again. */
	    if (retryInterval <= 0) {
		reason = "AFS not running";
		if (!interactive || opt.failSilently)
		    break;
		flag = MessageBox(hwndOwner,
				   "AFS is still starting.  Retry?",
				   "AFS Logon",
				   MB_ICONQUESTION | MB_RETRYCANCEL);
		if (flag == IDCANCEL)
		    break;

		/* Wait just a little while and try again */
		retryInterval = opt.retryInterval;
	    }

	  sleeping:
	    Sleep(sleepInterval * 1000);
	    retryInterval -= sleepInterval;
	}
    }
    DebugEvent0("while loop exited");

    /* remove any kerberos 5 tickets currently held by the SYSTEM account
     * for this user 
     */

    if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
#ifdef KFW_LOGON
	sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
	KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
#endif
	KFW_AFS_destroy_tickets_for_principal(uname);
    }

    if (code) {
	char msg[128];
	HANDLE h;
	char *ptbuf[1];

	StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);

	if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
	    MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);

	h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
	ptbuf[0] = msg;
	ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
		     1, 0, ptbuf, NULL);
	DeregisterEventSource(h);
	    
        code = MapAuthError(code);
        SetLastError(code);

        if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
        {
            if (*lpLogonScript)
                LocalFree(*lpLogonScript);
            *lpLogonScript = NULL;
            if (!afsWillAutoStart)	// its not running, so if not autostart or integrated logon then just skip
                code = 0;
        }
    }

    if (opt.theseCells) free(opt.theseCells);
    if (opt.smbName) free(opt.smbName);
    if (opt.realm) free(opt.realm);

    DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
    return code;
}       
Example #6
0
/* Get domain specific configuration info.  We are returning void because if anything goes wrong
   we just return defaults.
 */
void 
GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
    HKEY hkParm = NULL; /* Service parameter */
    HKEY hkNp = NULL;   /* network provider key */
    HKEY hkDoms = NULL; /* domains key */
    HKEY hkDom = NULL;  /* DOMAINS/domain key */
    HKEY hkTemp = NULL;
    LONG rv;
    DWORD dwSize;
    DWORD dwType;
    DWORD dwDummy;
    char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
    char *effDomain = NULL;

    memset(opt, 0, sizeof(LogonOptions_t));

    DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
    /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
    opt->flags = LOGON_FLAG_REMOTE;
    if(domain) {
        dwSize = MAX_COMPUTERNAME_LENGTH + 1;
        if(GetComputerName(computerName, &dwSize)) {
            if(!cm_stricmp_utf8(computerName, domain)) {
                effDomain = "LOCALHOST";
                opt->flags = LOGON_FLAG_LOCAL;
            }
        }
        if (effDomain == NULL)
            effDomain = domain;
    }

    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
    if(rv != ERROR_SUCCESS) {
        hkParm = NULL;
        DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
    }

    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
    if(rv != ERROR_SUCCESS) {
        hkNp = NULL;
        DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
    }

    if(hkNp) {
        rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
        if( rv != ERROR_SUCCESS ) {
            hkDoms = NULL;
            DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
        }
    }

    if(hkDoms && effDomain) {
        rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
        if( rv != ERROR_SUCCESS ) {
            hkDom = NULL;
            DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
            /* If none of the domains match, we shouldn't use the domain key either */
            RegCloseKey(hkDoms);
            hkDoms = NULL;
        }
    } else
        DebugEvent0("Not opening domain key");

    /* Each individual can either be specified on the domain key, the domains key or in the
       net provider key.  They fail over in that order.  If none is found, we just use the 
       defaults. */

    /* LogonOption */
    LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);

    /* FailLoginsSilently */
    dwSize = sizeof(dwDummy);
    rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
    if (rv != ERROR_SUCCESS)
        LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
    opt->failSilently = dwDummy ? 1 :0;

    /* Retry interval */
    LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);

    /* Sleep interval */
    LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);

    if(!ISLOGONINTEGRATED(opt->LogonOption)) {
        DebugEvent0("Integrated logon disabled");
        goto cleanup; /* no need to lookup the logon script */
    }

    /* come up with SMB username */
    if(ISHIGHSECURITY(opt->LogonOption)) {
        DebugEvent0("High Security Mode active");
        opt->smbName = malloc( MAXRANDOMNAMELEN );
        if (opt->smbName == NULL)
            goto cleanup;
        GenRandomName(opt->smbName);
    } else if (lpLogonId) {
        /* username and domain for logon session is not necessarily the same as
           username and domain passed into network provider. */
        PSECURITY_LOGON_SESSION_DATA plsd=NULL;
        char lsaUsername[MAX_USERNAME_LENGTH]="";
        char lsaDomain[MAX_DOMAIN_LENGTH]="";
        size_t len, tlen;
        NTSTATUS Status;

        Status = LsaGetLogonSessionData(lpLogonId, &plsd);
        if ( FAILED(Status) || plsd == NULL ) {
            DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
            goto bad_strings;
        }
        
        if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
            goto bad_strings;

        if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
            goto bad_strings;

        DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);

        if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
            len = tlen;
        else
            goto bad_strings;

        if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
            len += tlen;
        else
            goto bad_strings;

        len += 2;

        opt->smbName = malloc(len);
        if (opt->smbName == NULL)
            goto cleanup;

        StringCbCopy(opt->smbName, len, lsaDomain);
        StringCbCat(opt->smbName, len, "\\");
        StringCbCat(opt->smbName, len, lsaUsername);

        strlwr(opt->smbName);

      bad_strings:
        if (plsd)
            LsaFreeReturnBuffer(plsd);
    }
    if (opt->smbName == NULL) {
        size_t len;

        DebugEvent("Constructing username using [%s] and [%s]",
                   username, domain);
 
        len = strlen(username) + strlen(domain) + 2;

        opt->smbName = malloc(len);
        if (opt->smbName == NULL)
            goto cleanup;

        StringCbCopy(opt->smbName, len, domain);
        StringCbCat(opt->smbName, len, "\\");
        StringCbCat(opt->smbName, len, username);

        strlwr(opt->smbName);
    }

    DebugEvent0("Looking up logon script");
    /* Logon script */
    /* First find out where the key is */
    hkTemp = NULL;
    rv = ~ERROR_SUCCESS;
    dwType = 0;
    if(hkDom)
        rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
    if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
        hkTemp = hkDom;
        DebugEvent0("Located logon script in hkDom");
    }
    else if(hkDoms) {
        rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
        if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
            hkTemp = hkDoms;
            DebugEvent0("Located logon script in hkDoms");
        }
        /* Note that the LogonScript in the NP key is only used if we are doing high security. */
        else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
            rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
            if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
                hkTemp = hkNp;
                DebugEvent0("Located logon script in hkNp");
            }
        }
    }

    if(hkTemp) {
        WCHAR *regscript	= NULL;
        WCHAR *regexscript	= NULL;
        WCHAR *regexuscript	= NULL;
        WCHAR *wuname		= NULL;
        HRESULT hr;

        size_t len;

        StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
        len ++;

        wuname = malloc(len * sizeof(WCHAR));
        if (!wuname)
            goto doneLogonScript;
        MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));

        DebugEvent("Username is set for [%S]", wuname);

        /* dwSize still has the size of the required buffer in bytes. */
        regscript = malloc(dwSize);
        if (!regscript)
            goto doneLogonScript;
        rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
        if(rv != ERROR_SUCCESS) {/* what the ..? */
            DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
            goto doneLogonScript;
        }

        DebugEvent("Found logon script [%S]", regscript);

        if(dwType == REG_EXPAND_SZ) {
            DWORD dwReq;

            dwSize += MAX_PATH * sizeof(WCHAR);  /* make room for environment expansion. */
            regexscript = malloc(dwSize);
            if (!regexscript)
                goto doneLogonScript;
            dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
            free(regscript);
            regscript = regexscript;
            regexscript = NULL;
            if(dwReq > (dwSize / sizeof(WCHAR))) {
                DebugEvent0("Overflow while expanding environment strings.");
                goto doneLogonScript;
            }
        }

        DebugEvent("After expanding env strings [%S]", regscript);

        if(wcsstr(regscript, L"%s")) {
            dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
            regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
            if (!regexuscript)
                goto doneLogonScript;
            hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
        } else {
            regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
            if (!regexuscript)
                goto doneLogonScript;
            hr = StringCbCopyW(regexuscript, dwSize, regscript);
        }

        DebugEvent("After expanding username [%S]", regexuscript);

        if(hr == S_OK)
            opt->logonScript = regexuscript;
        else
            LocalFree(regexuscript);

      doneLogonScript:
        if(wuname) free(wuname);
        if(regscript) free(regscript);
        if(regexscript) free(regexscript);
    }

    DebugEvent0("Looking up TheseCells");
    /* TheseCells */
    /* First find out where the key is */
    hkTemp = NULL;
    rv = ~ERROR_SUCCESS;
    dwSize = 0;
    if (hkDom)
        rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
    if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
        hkTemp = hkDom;
        DebugEvent("Located TheseCells in hkDom size %d", dwSize);
    } else if (hkDoms) {
        rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
        if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
            hkTemp = hkDoms;
            DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
        } else if (hkNp) {
            rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
            if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
                hkTemp = hkNp;
                DebugEvent("Located TheseCells in hkNp size %d", dwSize);
            }
        }
    }

    if (hkTemp) {
        CHAR * thesecells = NULL;

        /* dwSize still has the size of the required buffer in bytes. */
        thesecells = malloc(dwSize*2);
        if (!thesecells)
            goto doneTheseCells;
        dwSize *= 2;
        SetLastError(0);
        rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
        if(rv != ERROR_SUCCESS) {/* what the ..? */
            DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
            goto doneTheseCells;
        }

        DebugEvent("Found TheseCells [%s]", thesecells);
        opt->theseCells = thesecells;
        thesecells = NULL;

      doneTheseCells:
        if (thesecells) free(thesecells);
    }

    DebugEvent0("Looking up Realm");
    /* Realm */
    /* First find out where the key is */
    hkTemp = NULL;
    rv = ~ERROR_SUCCESS;
    dwSize = 0;
    if (hkDom)
        rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
    if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
        hkTemp = hkDom;
        DebugEvent("Located Realm in hkDom size %d", dwSize);
    } else if (hkDoms) {
        rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
        if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
            hkTemp = hkDoms;
            DebugEvent("Located Realm in hkDoms size %d", dwSize);
        } else if (hkNp) {
            rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
            if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
                hkTemp = hkNp;
                DebugEvent("Located Realm in hkNp size %d", dwSize);
            }
        }
    }

    if (hkTemp) {
        CHAR * realm = NULL;

        /* dwSize still has the size of the required buffer in bytes. */
        realm = malloc(dwSize*2);
        if (!realm)
            goto doneRealm;
        dwSize *=2;
        SetLastError(0);
        rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
        if(rv != ERROR_SUCCESS) {/* what the ..? */
            DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
            goto doneRealm;
        }

        DebugEvent("Found Realm [%s]", realm);
        opt->realm = realm;
        realm = NULL;

      doneRealm:
        if (realm) free(realm);
    }

  cleanup:
    if(hkNp) RegCloseKey(hkNp);
    if(hkDom) RegCloseKey(hkDom);
    if(hkDoms) RegCloseKey(hkDoms);
    if(hkParm) RegCloseKey(hkParm);
}