authcomp_srv.c

#include <stdio.h>
#include <strings.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <assert.h>
#include <pwd.h>
#include <lwp.h>
#include <rpc2.h>
#include "auth.h"
#include "comp.h"

/*
This data structure provides per-connection info.  It is
created on every new connection and ceases to exist after AuthQuit().
*/
struct UserInfo {
    int Creation; /* Time at which this connection was created */
    /* other fields would go here */
}

int NewCLWP(), AuthLWP(), CompLWP(); /* bodies of LWPs */
void DebugOn(), DebugOff(); /* signal handlers */

void main()
{
    int mypid;

    signal(SIGEMT, DebugOn);
    signal(SIGIOT, DebugOff);

    InitRPC();
    LWP_CreateProcess(AuthLWP, 4096, LWP_NORMAL_PRIORITY, "AuthLWP", NULL,
                      &mypid);
    LWP_CreateProcess(CompLWP, 4096, LWP_NORMAL_PRIORITY, "CompLWP", NULL,
                      &mypid);
    LWP_WaitProcess(main); /* sleep here forever; no one will ever wake me up */
}

void AuthLWP(char *p)
/* char *p; single parameter passed to LWP_CreateProcess() */
{
    RPC2_RequestFilter reqfilter;
    RPC2_PacketBuffer *reqbuffer;
    RPC2_Handle cid;
    int rc;
    char *pp;

    /*  Set filter to accept  auth requests on new or existing connections */
    reqfilter.FromWhom              = ONESUBSYS;
    reqfilter.OldOrNew              = OLDORNEW;
    reqfilter.ConnOrSubsys.SubsysId = AUTHSUBSYSID;

    while (1) {
        cid = 0;

        rc = RPC2_GetRequest(&reqfilter, &cid, &reqbuffer, NULL, NULL, NULL,
                             NULL);
        if (rc < RPC2_WLIMIT)
            HandleRPCError(rc, cid);

        rc = auth_ExecuteRequest(cid, reqbuffer);
        if (rc < RPC2_WLIMIT)
            HandleRPCError(rc, cid);

        pp = NULL;
        if (RPC2_GetPrivatePointer(cid, &pp) != RPC2_SUCCESS || pp == NULL)
            RPC2_Unbind(cid); /* This was almost certainly an AuthQuit() call */
    }
}

void CompLWP(char *p)
{
    RPC2_RequestFilter reqfilter;
    RPC2_PacketBuffer *reqbuffer;
    RPC2_Handle cid;
    int rc;
    char *pp;

    /* Set filter  to accept  comp requests on new or existing connections */
    reqfilter.FromWhom              = ONESUBSYS;
    reqfilter.OldOrNew              = OLDORNEW;
    reqfilter.ConnOrSubsys.SubsysId = COMPSUBSYSID;

    while (1) {
        cid = 0;
        rc  = RPC2_GetRequest(&reqfilter, &cid, &reqbuffer, NULL, NULL, NULL,
                              NULL);
        if (rc < RPC2_WLIMIT)
            HandleRPCError(rc, cid);

        rc = comp_ExecuteRequest(cid, reqbuffer);
        if (rc < RPC2_WLIMIT)
            HandleRPCError(rc, cid);

        pp = NULL;
        if (RPC2_GetPrivatePointer(cid, &pp) != RPC2_SUCCESS || pp == NULL)
            RPC2_Unbind(cid); /* This was almost certainly an CompQuit() call */
    }
}

/*
Bodies of Auth RPC routines
*/

void S_AuthNewConn(RPC2_Handle cid, RPC2_Integer seType, RPC2_Integer secLevel,
                   RPC2_Integer encType, RPC2_CountedBS *cIdent)
{
    struct UserInfo *p;

    p = (struct UserInfo *)malloc(sizeof(struct UserInfo));
    RPC2_SetPrivatePointer(cid, p);
    p->Creation = time(0);
}

int S_AuthQuit(RPC2_Handle cid)
/*
Get rid of user state; note that we do not do RPC2_Unbind() here, because this
request itself has to complete.  The invoking server LWP therefore checks to
see if this connection can be unbound.
*/
{
    struct UserInfo *p;
    RPC2_GetPrivatePointer(cid, &p);
    assert(p != NULL); /* we have a bug then */
    free(p);
    RPC2_SetPrivatePointer(cid, NULL);
    return (AUTHSUCCESS);
}

int S_AuthUserId(RPC2_Handle cid, char *userName, int *userId)
{
    struct passwd *pw;
    if ((pw = getpwnam(userName)) == NULL)
        return (AUTHFAILED);

    *userId = pw->pw_uid;
    return (AUTHSUCCESS);
}

int S_AuthUserName(RPC2_Handle cid, int userId, RPC2_BoundedBS *userName)
{
    struct passwd *pw;
    if ((pw = getpwuid(userId)) == NULL)
        return (AUTHFAILED);

    strcpy(userName->SeqBody, pw->pw_name);
    /* we hope the buffer is big enough */
    userName->SeqLen = 1 + strlen(pw->pw_name);
    return (AUTHSUCCESS);
}

int S_AuthUserInfo(RPC2_Handle cid, int userId, AuthInfo *uInfo)
{
    struct passwd *pw;
    if ((pw = getpwuid(userId)) == NULL)
        return (AUTHFAILED);

    uInfo->GroupId = pw->pw_gid;
    strcpy(uInfo->HomeDir, pw->pw_dir);
    return (AUTHSUCCESS);
}

/*
Bodies of Comp RPC routines
*/
void S_CompNewConn(RPC2_Handle cid, RPC2_Integer seType, RPC2_Integer secLevel,
                   RPC2_Integer encType, RPC2_CountedBS *cIdent)
{
    struct UserInfo *p;

    p = (struct UserInfo *)malloc(sizeof(struct UserInfo));
    RPC2_SetPrivatePointer(cid, p);
    p->Creation = time(0);
}

int S_CompQuit(RPC2_Handle cid)
/*
Get rid of user state; note that we do not do RPC2_Unbind() here, because this
request itself has to complete.  The invoking server LWP therefore checks to
see if this connection can be unbound.
*/
{
    struct UserInfo *p;
    RPC2_GetPrivatePointer(cid, &p);
    assert(p != NULL); /* we have a bug then */
    free(p);
    RPC2_SetPrivatePointer(cid, NULL);
    return (0);
}

int S_CompSquare(RPC2_Handle cid, int x)
{
    return (x * x);
}

int S_CompCube(RPC2_Handle cid, int x)
{
    return (x * x * x);
}

int S_CompAge(RPC2_Handle cid, int x)
{
    struct UserInfo *p;
    assert(RPC2_GetPrivatePointer(cid, &p) == RPC2_SUCCESS);
    return (time(0) - p->Creation);
}

/*
RPC Initialization and Error handling
*/
void InitRPC()
{
    int mylpid = -1;
    RPC2_PortalIdent portalid, *portallist[1];
    RPC2_SubsysIdent subsysid;
    long rc;

    assert(LWP_Init(LWP_VERSION, LWP_NORMAL_PRIORITY, &mylpid) == LWP_SUCCESS);

    portalid.Tag                  = RPC2_PORTALBYINETNUMBER;
    portalid.Value.InetPortNumber = htons(AUTHPORTAL);
    portallist[0]                 = &portalid;

    rc = RPC2_Init(RPC2_VERSION, 0, portallist, 1, -1, NULL);
    if (rc != RPC2_SUCCESS) {
        fprintf(stderr, "RPC2_Init: failed with %ld\n", rc);
        exit(1);
    }

    subsysid.Tag            = RPC2_SUBSYSBYID;
    subsysid.Value.SubsysId = AUTHSUBSYSID;
    assert(RPC2_Export(&subsysid) == RPC2_SUCCESS);

    subsysid.Value.SubsysId = COMPSUBSYSID;
    assert(RPC2_Export(&subsysid) == RPC2_SUCCESS);
}

void HandleRPCError(int rCode, RPC2_Handle connId)
{
    fprintf(stderr, "exserver: %s\n", RPC2_ErrorMsg(rCode));
    if (rCode < RPC2_FLIMIT && connId != 0)
        RPC2_Unbind(connId);
}

void DebugOn()
{
    RPC2_DebugLevel = 100;
}

void DebugOff()
{
    RPC2_DebugLevel = 0;
}