Ejemplo n.º 1
0
/* Implements the remote setpag(2) call. Note that unlike the standard call,
 * here we also get back the new pag value; we need this so that the caller
 * can add it to its group list via setgroups() */
afs_int32
SRMTSYS_SetPag(struct rx_call *call, clientcred *creds, afs_int32 *newpag,
	       afs_int32 *errornumber)
{
    afs_uint32 blob[PIOCTL_HEADER];
    struct ViceIoctl data;
    afs_int32 error;

    *errornumber = 0;
    SETCLIENTCONTEXT(blob, rx_HostOf(rx_PeerOf(rx_ConnectionOf(call))), creds->uid,
		     creds->group0, creds->group1, PSETPAG, NFS_EXPORTER);
    data.in = (caddr_t) blob;
    data.in_size = sizeof(blob);
    data.out = (caddr_t) blob;
    data.out_size = sizeof(blob);
    /* force local pioctl call */
    error = lpioctl(0, _VICEIOCTL(PSetClientContext), &data, 1);
    if (error) {
	if (errno == PSETPAG) {
	    *newpag = blob[0];	/* new pag value */
	} else
	    *errornumber = errno;
    }
    return 0;
}
Ejemplo n.º 2
0
afs_int32
SBOZO_AddKey(struct rx_call *acall, afs_int32 an, struct bozo_key *akey)
{
    afs_int32 code;
    char caller[MAXKTCNAMELEN];
    rxkad_level enc_level = rxkad_clear;
    int noauth;

    if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
	code = BZACCESS;
	goto fail;
    }
    noauth = afsconf_GetNoAuthFlag(bozo_confdir);
    rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0);
    if ((!noauth) && (enc_level != rxkad_crypt)) {
	code = BZENCREQ;
	goto fail;
    }
    if (DoLogging)
	bozo_Log("%s is executing AddKey\n", caller);

    code = afsconf_AddKey(bozo_confdir, an, akey->data, 0);
    if (code == AFSCONF_KEYINUSE)
	code = BZKEYINUSE;	/* Unique code for afs rpc calls */
  fail:
    osi_auditU(acall, BOS_AddKeyEvent, code, AUD_END);
    return code;
}
Ejemplo n.º 3
0
int
SRXAFSCB_CallBack(struct rx_call *a_call, struct AFSCBFids *a_fids,
		  struct AFSCBs *a_callbacks)
{
    int i;		/*Loop variable */
    struct AFSFid *tfid;	/*Ptr to current fid */
    struct rx_connection *tconn;	/*Call's connection */
    int code = 0;
    XSTATS_DECLS;

    RX_AFS_GLOCK();

    XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);

    AFS_STATCNT(SRXAFSCB_CallBack);
    if (!(tconn = rx_ConnectionOf(a_call)))
	return (0);
    tfid = (struct AFSFid *)a_fids->AFSCBFids_val;

    /*
     * For now, we ignore callbacks, since the File Server only *breaks*
     * callbacks at present.
     */
    for (i = 0; i < a_fids->AFSCBFids_len; i++)
	ClearCallBack(tconn, &tfid[i]);

    XSTATS_END_TIME;

    RX_AFS_GUNLOCK();

    return (0);

}				/*SRXAFSCB_CallBack */
Ejemplo n.º 4
0
afs_int32
SBOZO_ListKeys(struct rx_call *acall, afs_int32 an, afs_int32 *akvno,
	       struct bozo_key *akey, struct bozo_keyInfo *akeyinfo)
{
    struct afsconf_keys tkeys;
    afs_int32 code;
    struct stat tstat;
    int noauth = 0;
    char caller[MAXKTCNAMELEN];
    rxkad_level enc_level = rxkad_clear;

    if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
	code = BZACCESS;
	goto fail;
    }
    if (DoLogging)
	bozo_Log("%s is executing ListKeys\n", caller);

    code = afsconf_GetKeys(bozo_confdir, &tkeys);
    if (code)
	goto fail;

    if (tkeys.nkeys <= an) {
	code = BZDOM;
	goto fail;
    }
    *akvno = tkeys.key[an].kvno;
    memset(akeyinfo, 0, sizeof(struct bozo_keyInfo));

    noauth = afsconf_GetNoAuthFlag(bozo_confdir);
    rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0);
    /*
     * only return actual keys in noauth or if this is an encrypted connection
     */

    if ((noauth) || (enc_level == rxkad_crypt)) {
	memcpy(akey, tkeys.key[an].key, 8);
    } else
	memset(akey, 0, 8);

    code = stat(AFSDIR_SERVER_KEY_FILEPATH, &tstat);
    if (code == 0) {
	akeyinfo->mod_sec = tstat.st_mtime;
    }

    /* This will return an error if the key is 'bad' (bad checksum, weak DES
     * key, etc). But we don't care, since we can still return the other
     * information about the key, so ignore the result. */
    (void)ka_KeyCheckSum(tkeys.key[an].key, &akeyinfo->keyCheckSum);

  fail:
    if (noauth)
	osi_auditU(acall, BOS_UnAuthListKeysEvent, code, AUD_END);
    osi_auditU(acall, BOS_ListKeysEvent, code, AUD_END);
    return code;
}
Ejemplo n.º 5
0
/* services available on incoming message port */
int
SBC_Print(struct rx_call *acall, afs_int32 acode, afs_int32 aflags,
	 char *amessage)
{
    struct rx_connection *tconn;
    struct rx_peer *tpeer;

    tconn = rx_ConnectionOf(acall);
    tpeer = rx_PeerOf(tconn);
    printf("From %08x: %s <%d>\n", tpeer->host, amessage, acode);
    return 0;
}
Ejemplo n.º 6
0
static int
rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall,
	       struct rx_identity **identity)
{
    char tname[MAXKTCNAMELEN];	/* authentication from ticket */
    char tinst[MAXKTCNAMELEN];
    char tcell[MAXKTCREALMLEN];

    afs_uint32 exp;
    int code;

    /* get auth details from server connection */
    code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, &exp, tname,
			       tinst, tcell, NULL);
    if (code)
	return 0;		/* bogus connection/other error */

    return kerberosSuperUser(adir, tname, tinst, tcell, identity);
}
Ejemplo n.º 7
0
/*!
 * Check whether the user authenticated on a given RX call is a super
 * user or not. If they are, return a pointer to the identity of that
 * user.
 *
 * @param[in] adir
 * 	The configuration directory currently in use
 * @param[in] acall
 * 	The RX call whose authenticated identity is being checked
 * @param[out] identity
 * 	The RX identity of the user. Caller must free this structure.
 * @returns
 * 	True if the user is a super user, or if the server is running
 * 	in noauth mode. Otherwise, false.
 */
afs_int32
afsconf_SuperIdentity(struct afsconf_dir *adir, struct rx_call *acall,
		      struct rx_identity **identity)
{
    struct rx_connection *tconn;
    afs_int32 code;
    int flag;

    LOCK_GLOBAL_MUTEX;
    if (!adir) {
	UNLOCK_GLOBAL_MUTEX;
	return 0;
    }

    if (afsconf_GetNoAuthFlag(adir)) {
	if (identity)
	    *identity = rx_identity_new(RX_ID_KRB4, AFS_NOAUTH_NAME,
	                                AFS_NOAUTH_NAME, AFS_NOAUTH_LEN);
	UNLOCK_GLOBAL_MUTEX;
	return 1;
    }

    tconn = rx_ConnectionOf(acall);
    code = rx_SecurityClassOf(tconn);
    if (code == RX_SECIDX_NULL) {
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* not authenticated at all, answer is no */
    } else if (code == RX_SECIDX_VAB) {
	/* bcrypt tokens */
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* not supported any longer */
    } else if (code == RX_SECIDX_KAD) {
	flag = rxkadSuperUser(adir, acall, identity);
	UNLOCK_GLOBAL_MUTEX;
	return flag;
    } else {			/* some other auth type */
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* mysterious, just say no */
    }
}
Ejemplo n.º 8
0
/* Implements the remote pioctl(2) call */
afs_int32
SRMTSYS_Pioctl(struct rx_call *call, clientcred *creds, char *path,
	       afs_int32 cmd, afs_int32 follow, rmtbulk *InData,
	       rmtbulk *OutData, afs_int32 *errornumber)
{
    afs_int32 error;
    struct ViceIoctl data;
    char *pathp = path;
    afs_uint32 blob[PIOCTL_HEADER];

    *errornumber = 0;
    SETCLIENTCONTEXT(blob, rx_HostOf(rx_PeerOf(rx_ConnectionOf(call))), creds->uid,
		     creds->group0, creds->group1, cmd, NFS_EXPORTER);
    data.in = malloc(InData->rmtbulk_len + PIOCTL_HEADER * sizeof(afs_int32));
    if (!data.in)
	return (-1);		/* helpless here */
    if (!strcmp(path, NIL_PATHP))
	pathp = (char *)0;	/* It meant to be NIL */
    memcpy(data.in, blob, sizeof(blob));
    inparam_conversion(cmd, InData->rmtbulk_val, 1);
    memcpy(data.in + sizeof(blob), InData->rmtbulk_val, InData->rmtbulk_len);
    data.in_size = InData->rmtbulk_len + PIOCTL_HEADER * sizeof(afs_int32);
    data.out = OutData->rmtbulk_val;
    data.out_size = OutData->rmtbulk_len;
    /* force local pioctl call */
    error = lpioctl(pathp, _VICEIOCTL(PSetClientContext), &data, follow);
    if (error) {
	*errornumber = errno;
    } else {
	/* Send the results back in network order */
	outparam_conversion(cmd, data.out, 0);
    }
    free(data.in);
    /* Note that we return success (i.e. 0) even when pioctl fails; that's
     * because the actual errno is passed back via 'errornumber' and this call
     * MUST return success error in order to get that OUT params back (YUCK!)
     */
    return (0);
}
Ejemplo n.º 9
0
/* make sure user authenticated on rx call acall is in list of valid
    users. Copy the "real name" of the authenticated user into namep
    if a pointer is passed.
*/
afs_int32
afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
{
    struct rx_connection *tconn;
    afs_int32 code;
    int flag;

    LOCK_GLOBAL_MUTEX;
    if (!adir) {
	UNLOCK_GLOBAL_MUTEX;
	return 0;
    }

    if (afsconf_GetNoAuthFlag(adir)) {
	if (namep)
	    strcpy(namep, "<NoAuth>");
	UNLOCK_GLOBAL_MUTEX;
	return 1;
    }

    tconn = rx_ConnectionOf(acall);
    code = rx_SecurityClassOf(tconn);
    if (code == 0) {
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* not authenticated at all, answer is no */
    } else if (code == 1) {
	/* bcrypt tokens */
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* not supported any longer */
    } else if (code == 2) {
	flag = rxkadSuperUser(adir, acall, namep);
	UNLOCK_GLOBAL_MUTEX;
	return flag;
    } else {			/* some other auth type */
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* mysterious, just say no */
    }
}
Ejemplo n.º 10
0
/* make sure user authenticated on rx call acall is in list of valid
    users. Copy the "real name" of the authenticated user into namep
    if a pointer is passed.
*/
afs_int32
afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
{
    register struct rx_connection *tconn;
    register afs_int32 code;
    int flag;

    LOCK_GLOBAL_MUTEX;
    if (!adir) {
	UNLOCK_GLOBAL_MUTEX;
	return 0;
    }

    if (afsconf_GetNoAuthFlag(adir)) {
	if (namep)
	    strcpy(namep, "<NoAuth>");
	UNLOCK_GLOBAL_MUTEX;
	return 1;
    }

    tconn = rx_ConnectionOf(acall);
    code = rx_SecurityClassOf(tconn);
    if (code == 0) {
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* not authenticated at all, answer is no */
    } else if (code == 1) {
	/* bcrypt tokens */
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* not supported any longer */
    } else if (code == 2) {
	char tname[MAXKTCNAMELEN];	/* authentication from ticket */
	char tinst[MAXKTCNAMELEN];
	char tcell[MAXKTCREALMLEN];
	char tcell_l[MAXKTCREALMLEN];
	char *tmp;

	/* keep track of which one actually authorized request */
	char uname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];

	afs_uint32 exp;
	static char lcell[MAXCELLCHARS] = "";
	static char lrealms[AFS_NUM_LREALMS][AFS_REALM_SZ];
	static int  num_lrealms = -1;
	int lrealm_match = 0, i;

	/* get auth details from server connection */
	code =
	    rxkad_GetServerInfo(acall->conn, NULL, &exp, tname, tinst, tcell,
				NULL);
	if (code) {
	    UNLOCK_GLOBAL_MUTEX;
	    return 0;		/* bogus connection/other error */
	}

	/* don't bother checking anything else if tix have expired */
#ifdef AFS_PTHREAD_ENV
	if (exp < clock_Sec()) {
#else
	if (exp < FT_ApproxTime()) {
#endif
	    UNLOCK_GLOBAL_MUTEX;
	    return 0;		/* expired tix */
	}

	/* generate lowercased version of cell name */
	strcpy(tcell_l, tcell);
	tmp = tcell_l;
	while (*tmp) {
	    *tmp = tolower(*tmp);
	    tmp++;
	}

	/* determine local cell name. It's static, so will only get
	 * calculated the first time through */
	if (!lcell[0])
	    afsconf_GetLocalCell(adir, lcell, sizeof(lcell));

	/* if running a krb environment, also get the local realm */
	/* note - this assumes AFS_REALM_SZ <= MAXCELLCHARS */
	/* just set it to lcell if it fails */
	if (num_lrealms == -1) {
	    for (i=0; i<AFS_NUM_LREALMS; i++) {
		if (afs_krb_get_lrealm(lrealms[i], i) != 0 /*KSUCCESS*/)
		    break;
	    }

	    if (i == 0) {
		strncpy(lrealms[0], lcell, AFS_REALM_SZ);
		num_lrealms = 1;
	    } else {
		num_lrealms = i;
	    }
	}

	/* See if the ticket cell matches one of the local realms */
	lrealm_match = 0;
	for ( i=0;i<num_lrealms;i++ ) {
	    if (!strcasecmp(lrealms[i], tcell)) {
		lrealm_match = 1;
		break;
	    }
	}

	/* If yes, then make sure that the name is not present in 
	 * an exclusion list */
	if (lrealm_match) {
	    if (tinst[0])
		snprintf(uname,sizeof(uname),"%s.%s@%s",tname,tinst,tcell);
	    else
		snprintf(uname,sizeof(uname),"%s@%s",tname,tcell);

	    if (afs_krb_exclusion(uname))
		lrealm_match = 0;
	}

	/* start with no uname and no authorization */
	strcpy(uname, "");
	flag = 0;

	/* localauth special case */
	if (strlen(tinst) == 0 && strlen(tcell) == 0
	    && !strcmp(tname, AUTH_SUPERUSER)) {
	    strcpy(uname, "<LocalAuth>");
	    flag = 1;

	    /* cell of connection matches local cell or one of the realms */
	} else if (!strcasecmp(tcell, lcell) || lrealm_match) {
	    if ((tmp = CompFindUser(adir, tname, ".", tinst, NULL))) {
		strcpy(uname, tmp);
		flag = 1;
#ifdef notyet
	    } else if ((tmp = CompFindUser(adir, tname, "/", tinst, NULL))) {
		strcpy(uname, tmp);
		flag = 1;
#endif
	    }
	    /* cell of conn doesn't match local cell or realm */
	} else {
	    if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell))) {
		strcpy(uname, tmp);
		flag = 1;
#ifdef notyet
	    } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell))) {
		strcpy(uname, tmp);
		flag = 1;
#endif
	    } else if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell_l))) {
		strcpy(uname, tmp);
		flag = 1;
#ifdef notyet
	    } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell_l))) {
		strcpy(uname, tmp);
		flag = 1;
#endif
	    }
	}

	if (namep)
	    strcpy(namep, uname);
	UNLOCK_GLOBAL_MUTEX;
	return flag;
    } else {			/* some other auth type */
	UNLOCK_GLOBAL_MUTEX;
	return 0;		/* mysterious, just say no */
    }
}
Ejemplo n.º 11
0
afs_int32
SDISK_SendFile(struct rx_call *rxcall, afs_int32 file,
	       afs_int32 length, struct ubik_version *avers)
{
    afs_int32 code;
    struct ubik_dbase *dbase = NULL;
    char tbuffer[1024];
    afs_int32 offset;
    struct ubik_version tversion;
    int tlen;
    struct rx_peer *tpeer;
    struct rx_connection *tconn;
    afs_uint32 otherHost = 0;
    char hoststr[16];
    char pbuffer[1028];
    int fd = -1;
    afs_int32 epoch = 0;
    afs_int32 pass;

    /* send the file back to the requester */

    dbase = ubik_dbase;

    if ((code = ubik_CheckAuth(rxcall))) {
	DBHOLD(dbase);
	goto failed;
    }

    /* next, we do a sanity check to see if the guy sending us the database is
     * the guy we think is the sync site.  It turns out that we might not have
     * decided yet that someone's the sync site, but they could have enough
     * votes from others to be sync site anyway, and could send us the database
     * in advance of getting our votes.  This is fine, what we're really trying
     * to check is that some authenticated bogon isn't sending a random database
     * into another configuration.  This could happen on a bad configuration
     * screwup.  Thus, we only object if we're sure we know who the sync site
     * is, and it ain't the guy talking to us.
     */
    offset = uvote_GetSyncSite();
    tconn = rx_ConnectionOf(rxcall);
    tpeer = rx_PeerOf(tconn);
    otherHost = ubikGetPrimaryInterfaceAddr(rx_HostOf(tpeer));
    if (offset && offset != otherHost) {
	/* we *know* this is the wrong guy */
	code = USYNC;
	DBHOLD(dbase);
	goto failed;
    }

    DBHOLD(dbase);

    /* abort any active trans that may scribble over the database */
    urecovery_AbortAll(dbase);

    ubik_print("Ubik: Synchronize database with server %s\n",
	       afs_inet_ntoa_r(otherHost, hoststr));

    offset = 0;
    UBIK_VERSION_LOCK;
    epoch = tversion.epoch = 0;		/* start off by labelling in-transit db as invalid */
    (*dbase->setlabel) (dbase, file, &tversion);	/* setlabel does sync */
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP",
	     ubik_dbase->pathName, (file<0)?"SYS":"",
	     (file<0)?-file:file);
    fd = open(pbuffer, O_CREAT | O_RDWR | O_TRUNC, 0600);
    if (fd < 0) {
	code = errno;
	goto failed_locked;
    }
    code = lseek(fd, HDRSIZE, 0);
    if (code != HDRSIZE) {
	close(fd);
	goto failed_locked;
    }
    pass = 0;
    memcpy(&ubik_dbase->version, &tversion, sizeof(struct ubik_version));
    UBIK_VERSION_UNLOCK;
    while (length > 0) {
	tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length);
#if !defined(AFS_PTHREAD_ENV)
	if (pass % 4 == 0)
	    IOMGR_Poll();
#endif
	code = rx_Read(rxcall, tbuffer, tlen);
	if (code != tlen) {
	    ubik_dprint("Rx-read length error=%d\n", code);
	    code = BULK_ERROR;
	    close(fd);
	    goto failed;
	}
	code = write(fd, tbuffer, tlen);
	pass++;
	if (code != tlen) {
	    ubik_dprint("write failed error=%d\n", code);
	    code = UIOERROR;
	    close(fd);
	    goto failed;
	}
	offset += tlen;
	length -= tlen;
    }
    code = close(fd);
    if (code)
	goto failed;

    /* sync data first, then write label and resync (resync done by setlabel call).
     * This way, good label is only on good database. */
    snprintf(tbuffer, sizeof(tbuffer), "%s.DB%s%d",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
#ifdef AFS_NT40_ENV
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
    code = unlink(pbuffer);
    if (!code)
	code = rename(tbuffer, pbuffer);
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
#endif
    if (!code)
	code = rename(pbuffer, tbuffer);
    UBIK_VERSION_LOCK;
    if (!code) {
	(*ubik_dbase->open) (ubik_dbase, file);
	code = (*ubik_dbase->setlabel) (dbase, file, avers);
    }
#ifdef AFS_NT40_ENV
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
    unlink(pbuffer);
#endif
    memcpy(&ubik_dbase->version, avers, sizeof(struct ubik_version));
    udisk_Invalidate(dbase, file);	/* new dbase, flush disk buffers */
#ifdef AFS_PTHREAD_ENV
    assert(pthread_cond_broadcast(&dbase->version_cond) == 0);
#else
    LWP_NoYieldSignal(&dbase->version);
#endif

failed_locked:
    UBIK_VERSION_UNLOCK;

failed:
    if (code) {
	unlink(pbuffer);
	/* Failed to sync. Allow reads again for now. */
	if (dbase != NULL) {
	    UBIK_VERSION_LOCK;
	    tversion.epoch = epoch;
	    (*dbase->setlabel) (dbase, file, &tversion);
	    UBIK_VERSION_UNLOCK;
	}
	ubik_print
	    ("Ubik: Synchronize database with server %s failed (error = %d)\n",
	     afs_inet_ntoa_r(otherHost, hoststr), code);
    } else {
	ubik_print("Ubik: Synchronize database completed\n");
    }
    DBRELE(dbase);
    return code;
}
Ejemplo n.º 12
0
int
SPAGCB_GetCreds(struct rx_call *a_call, afs_int32 a_uid,
                CredInfos *a_creds)
{
    struct unixuser *tu;
    CredInfo *tci;
    int bucket, count, i = 0, clen;
    char *cellname;

    RX_AFS_GLOCK();

    memset(a_creds, 0, sizeof(struct CredInfos));
    if ((rx_HostOf(rx_PeerOf(rx_ConnectionOf(a_call))) != afs_nfs_server_addr
	||  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7001))
#if 0 /* for debugging ONLY! */
	&&  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7901)
#endif
        ) {
	RX_AFS_GUNLOCK();
	return UAEPERM;
    }

    ObtainWriteLock(&afs_xuser, 823);

    /* count them first */
    bucket = UHash(a_uid);
    for (count = 0, tu = afs_users[bucket]; tu; tu = tu->next) {
	if (tu->uid == a_uid) count++;
    }

    if (!count) {
	ReleaseWriteLock(&afs_xuser);
	RX_AFS_GUNLOCK();
	return UAESRCH;
    }

    a_creds->CredInfos_val =
	(CredInfo *)afs_osi_Alloc(count * sizeof(CredInfo));
    if (!a_creds->CredInfos_val)
	goto out;
    a_creds->CredInfos_len = count;
    memset(a_creds->CredInfos_val, 0, count * sizeof(CredInfo));

    for (i = 0, tu = afs_users[bucket]; tu; tu = tu->next, i++) {
	if (tu->uid == a_uid && tu->cellinfo &&
	    (tu->states & UHasTokens) && !(tu->states & UTokensBad)) {

	    tci = &a_creds->CredInfos_val[i];
	    tci->vid               = tu->vid;
	    tci->ct.AuthHandle     = tu->ct.AuthHandle;
	    memcpy(tci->ct.HandShakeKey, tu->ct.HandShakeKey, 8);
	    tci->ct.ViceId         = tu->ct.ViceId;
	    tci->ct.BeginTimestamp = tu->ct.BeginTimestamp;
	    tci->ct.EndTimestamp   = tu->ct.EndTimestamp;

	    cellname = ((struct afspag_cell *)(tu->cellinfo))->cellname;
	    clen = strlen(cellname) + 1;
	    tci->cellname = afs_osi_Alloc(clen);
	    if (!tci->cellname)
		goto out;
	    memcpy(tci->cellname, cellname, clen);

	    tci->st.st_len = tu->stLen;
	    tci->st.st_val = afs_osi_Alloc(tu->stLen);
	    if (!tci->st.st_val) {
		afs_osi_Free(tci->cellname, clen);
		goto out;
	    }
	    memcpy(tci->st.st_val, tu->stp, tu->stLen);
	    if (tu->states & UPrimary)
		tci->states |= UPrimary;
	}
    }

    ReleaseWriteLock(&afs_xuser);
    RX_AFS_GUNLOCK();
    return 0;

out:
    if (a_creds->CredInfos_val) {
	while (i-- > 0) {
	    afs_osi_Free(a_creds->CredInfos_val[i].st.st_val,
			 a_creds->CredInfos_val[i].st.st_len);
	    afs_osi_Free(a_creds->CredInfos_val[i].cellname,
			 strlen(a_creds->CredInfos_val[i].cellname) + 1);
	}
	afs_osi_Free(a_creds->CredInfos_val, count * sizeof(CredInfo));
    }

    ReleaseWriteLock(&afs_xuser);
    RX_AFS_GUNLOCK();
    return UAENOMEM;
}
Ejemplo n.º 13
0
/*!
 * \brief called by the sync site to handle vote beacons; if aconn is null, this is a
 * local call
 *
 * \returns 0 or time when the vote was sent.  It returns 0 if we are
 * not voting for this sync site, or the time we actually voted yes, if
 * non-zero.
 */
afs_int32
SVOTE_Beacon(struct rx_call * rxcall, afs_int32 astate,
	     afs_int32 astart, struct ubik_version * avers,
	     struct ubik_tid * atid)
{
    afs_int32 otherHost;
    afs_int32 now;
    afs_int32 vote;
    struct rx_connection *aconn;
    struct rx_peer *rxp;
    struct ubik_server *ts;
    int isClone = 0;
    char hoststr[16];

    if (rxcall) {		/* caller's host */
	aconn = rx_ConnectionOf(rxcall);
	rxp = rx_PeerOf(aconn);
	otherHost = rx_HostOf(rxp);

	/* get the primary interface address for this host.  */
	/* This is the identifier that ubik uses. */
	otherHost = ubikGetPrimaryInterfaceAddr(otherHost);
	if (!otherHost) {
	    ubik_dprint("Received beacon from unknown host %s\n",
			afs_inet_ntoa_r(rx_HostOf(rxp), hoststr));
	    return 0;		/* I don't know about you: vote no */
	}
	for (ts = ubik_servers; ts; ts = ts->next) {
	    if (ts->addr[0] == otherHost)
		break;
	}
	if (!ts)
	    ubik_dprint("Unknown host %x has sent a beacon\n", otherHost);
	if (ts && ts->isClone)
	    isClone = 1;
    } else {
	otherHost = ubik_host[0];	/* this host */
	isClone = amIClone;
    }

    ubik_dprint("Received beacon type %d from host %s\n", astate,
		afs_inet_ntoa_r(otherHost, hoststr));

    /* compute the lowest server we've heard from.  We'll try to only vote for
     * this dude if we don't already have a synchronization site.  Also, don't
     * let a very old lowestHost confusing things forever.  We pick a new
     * lowestHost after BIGTIME seconds to limit the damage if this host
     * actually crashes.  Finally, we also count in this computation: don't
     * pick someone else if we're even better!
     *
     * Note that the test below must be <=, not <, so that we keep refreshing
     * lowestTime.  Otherwise it will look like we haven't heard from
     * lowestHost in a while and another host could slip in.  */


    /* First compute the lowest host we've heard from, whether we want them
     * for a sync site or not.  If we haven't heard from a site in BIGTIME
     * seconds, we ignore its presence in lowestHost: it may have crashed.
     * Note that we don't ever let anyone appear in our lowestHost if we're
     * lower than them, 'cause we know we're up. */
    /* But do not consider clones for lowesHost since they never may become
     * sync site */
    UBIK_VOTE_LOCK;
    now = FT_ApproxTime();	/* close to current time */
    if (!isClone
	&& (ntohl((afs_uint32)otherHost) <= ntohl((afs_uint32)vote_globals.lowestHost)
	    || vote_globals.lowestTime + BIGTIME < now)) {
	vote_globals.lowestTime = now;
	vote_globals.lowestHost = otherHost;
    }
    /* why do we need this next check?  Consider the case where each of two
     * servers decides the other is lowestHost.  Each stops sending beacons
     * 'cause the other is there.  Not obvious that this process terminates:
     * i.e. each guy could restart procedure and again think other side is
     * lowest.  Need to prove: if one guy in the system is lowest and knows
     * he's lowest, these loops don't occur.  because if someone knows he's
     * lowest, he will send out beacons telling others to vote for him. */
    if (!amIClone
	&& (ntohl((afs_uint32) ubik_host[0]) <= ntohl((afs_uint32)vote_globals.lowestHost)
	    || vote_globals.lowestTime + BIGTIME < now)) {
	vote_globals.lowestTime = now;
	vote_globals.lowestHost = ubik_host[0];
    }

    /* tell if we've heard from a sync site recently (even if we're not voting
     * for this dude yet).  After a while, time the guy out. */
    if (astate) {		/* this guy is a sync site */
	vote_globals.syncHost = otherHost;
	vote_globals.syncTime = now;
    } else if (vote_globals.syncTime + BIGTIME < now) {
	if (vote_globals.syncHost) {
	    ubik_dprint
		("Ubik: Lost contact with sync-site %s (NOT in quorum)\n",
		 afs_inet_ntoa_r(vote_globals.syncHost, hoststr));
	}
	vote_globals.syncHost = 0;
    }

    /* decide how to vote */
    vote = 0;			/* start off voting no */

    /* if we this guy isn't a sync site, we don't really have to vote for him.
     * We get to apply some heuristics to try to avoid weird oscillation sates
     * in the voting procedure. */
    if (astate == 0) {
	/* in here only if this guy doesn't claim to be a sync site */

	/* lowestHost is also trying for our votes, then just say no. */
	if (ntohl(vote_globals.lowestHost) != ntohl(otherHost)) {
	    goto done_zero;
	}

	/* someone else *is* a sync site, just say no */
	if (vote_globals.syncHost && vote_globals.syncHost != otherHost)
	    goto done_zero;
    } else if (vote_globals.lastYesHost == 0xffffffff && otherHost == ubik_host[0]) {
	/* fast startup if this is the only non-clone */
	int i = 0;
	for (ts = ubik_servers; ts; ts = ts->next) {
	    if (ts->addr[0] == otherHost)
		continue;
	    if (!ts->isClone)
		i++;
	}
	if (!i)
	    vote_globals.lastYesHost = otherHost;
    }


    if (isClone)
	goto done_zero;		/* clone never can become sync site */

    /* Don't promise sync site support to more than one host every BIGTIME
     * seconds.  This is the heart of our invariants in this system. */
    if (vote_globals.ubik_lastYesTime + BIGTIME < now || otherHost == vote_globals.lastYesHost) {
	if ((vote_globals.ubik_lastYesTime + BIGTIME < now) || (otherHost != vote_globals.lastYesHost)
	    || (vote_globals.lastYesState != astate)) {
	    /* A new vote or a change in the vote or changed quorum */
	    ubik_dprint("Ubik: vote 'yes' for %s %s\n",
			afs_inet_ntoa_r(otherHost, hoststr),
			(astate ? "(in quorum)" : "(NOT in quorum)"));
	}

	vote = now;		/* vote yes */
	vote_globals.ubik_lastYesTime = now;	/* remember when we voted yes */
	vote_globals.lastYesClaim = astart;	/* remember for computing when sync site expires */
	vote_globals.lastYesHost = otherHost;	/* and who for */
	vote_globals.lastYesState = astate;	/* remember if site is a sync site */
	vote_globals.ubik_dbVersion = *avers;	/* resync value */
	vote_globals.ubik_dbTid = *atid;	/* transaction id, if any, of active trans */
	UBIK_VOTE_UNLOCK;
	DBHOLD(ubik_dbase);
	urecovery_CheckTid(atid, 0);	/* check if current write trans needs aborted */
	DBRELE(ubik_dbase);
    } else {
	UBIK_VOTE_UNLOCK;
    }
    return vote;
done_zero:
    UBIK_VOTE_UNLOCK;
    return 0;
}
Ejemplo n.º 14
0
int
SRXAFSCB_InitCallBackState(struct rx_call *a_call)
{
    int i;
    struct vcache *tvc;
    struct rx_connection *tconn;
    struct rx_peer *peer;
    struct server *ts;
    int code = 0;
    XSTATS_DECLS;

    RX_AFS_GLOCK();

    XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
    AFS_STATCNT(SRXAFSCB_InitCallBackState);

    /*
     * Find the address of the host making this call
     */
    if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {

	afs_allCBs++;
	afs_oddCBs++;		/*Including any missed via create race */
	afs_evenCBs++;		/*Including any missed via create race */

	ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
			    0);
	if (ts) {
	    for (i = 0; i < VCSIZE; i++)
		for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
		    if (tvc->callback == ts) {
			ObtainWriteLock(&afs_xcbhash, 451);
			afs_DequeueCallback(tvc);
			tvc->callback = NULL;
			tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
			ReleaseWriteLock(&afs_xcbhash);
		    }
		}

	    /* capabilities need be requested again */
	    ObtainWriteLock(&afs_xserver, 877);
	    ts->flags &= ~SCAPS_KNOWN;
	    ReleaseWriteLock(&afs_xserver);
	}



	/* find any volumes residing on this server and flush their state */
	{
	    struct volume *tv;
	    int j;

	    for (i = 0; i < NVOLS; i++)
		for (tv = afs_volumes[i]; tv; tv = tv->next) {
		    for (j = 0; j < AFS_MAXHOSTS; j++)
			if (tv->serverHost[j] == ts)
			    afs_ResetVolumeInfo(tv);
		}
	}
	osi_dnlc_purge();	/* may be a little bit extreme */
    }

    XSTATS_END_TIME;

    RX_AFS_GUNLOCK();

    return (0);

}				/*SRXAFSCB_InitCallBackState */