Example #1
0
File: dopdu.c Project: aeppert/pcp
static int
do_creds(__pmPDU *pb)
{
    int		i;
    int		sts;
    int		version = UNKNOWN_VERSION;
    int		credcount;
    int		sender;
    __pmCred	*credlist = NULL;

    if ((sts = __pmDecodeCreds(pb, &sender, &credcount, &credlist)) < 0) {
	__pmNotifyErr(LOG_ERR, "do_creds: error decoding PDU: %s\n", pmErrStr(sts));
		return PM_ERR_IPC;
    }

    for (i = 0; i < credcount; i++) {
	if (credlist[i].c_type == CVERSION) {
	    version = credlist[i].c_vala;
	    if ((sts = __pmSetVersionIPC(clientfd, version)) < 0) {
		free(credlist);
		return sts;
	    }
	}
    }

    if (credlist)
	free(credlist);

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_APPL1)
	fprintf(stderr, "do_creds: pmlc version=%d\n", version);
#endif

    return sts;
}
Example #2
0
/* Establish a new socket connection to a client */
ClientInfo *
AcceptNewClient(int reqfd)
{
    static unsigned int	seq = 0;
    int			i, fd;
    __pmSockLen		addrlen;
    struct timeval	now;

    i = NewClient();
    addrlen = __pmSockAddrSize();
    fd = __pmAccept(reqfd, client[i].addr, &addrlen);
    if (fd == -1) {
        if (neterror() == EPERM) {
            __pmNotifyErr(LOG_NOTICE, "AcceptNewClient(%d): "
                          "Permission Denied\n", reqfd);
            client[i].fd = -1;
            DeleteClient(&client[i]);
            return NULL;
        }
        else {
            __pmNotifyErr(LOG_ERR, "AcceptNewClient(%d) __pmAccept: %s\n",
                          reqfd, netstrerror());
            Shutdown();
            exit(1);
        }
    }
    if (fd > maxClientFd)
        maxClientFd = fd;

    pmcd_openfds_sethi(fd);

    __pmFD_SET(fd, &clientFds);
    __pmSetVersionIPC(fd, UNKNOWN_VERSION);	/* before negotiation */
    __pmSetSocketIPC(fd);

    client[i].fd = fd;
    client[i].status.connected = 1;
    client[i].status.changes = 0;
    memset(&client[i].attrs, 0, sizeof(__pmHashCtl));

    /*
     * Note seq needs to be unique, but we're using a free running counter
     * and not bothering to check here ... unless we churn through
     * 4,294,967,296 (2^32) clients while one client remains connected
     * we won't have a problem
     */
    client[i].seq = seq++;
    __pmtimevalNow(&now);
    client[i].start = now.tv_sec;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_APPL0)
        fprintf(stderr, "AcceptNewClient(%d): client[%d] (fd %d)\n", reqfd, i, fd);
#endif
    pmcd_trace(TR_ADD_CLIENT, i, 0, 0);

    return &client[i];
}
Example #3
0
File: connect.c Project: tongfw/pcp
/*
 * client connects to pmcd handshake
 */
static int
__pmConnectHandshake(int fd, const char *hostname, int ctxflags, __pmHashCtl *attrs)
{
    __pmPDU	*pb;
    int		ok;
    int		version;
    int		challenge;
    int		sts;
    int		pinpdu;

    /* Expect an error PDU back from PMCD: ACK/NACK for connection */
    pinpdu = sts = __pmGetPDU(fd, ANY_SIZE, TIMEOUT_DEFAULT, &pb);
    if (sts == PDU_ERROR) {
	/*
	 * See comments in pmcd ... we actually get an extended error PDU
	 * from pmcd, of the form
	 *
	 *  :----------:-----------:
	 *  |  status  | challenge |
	 *  :----------:-----------:
	 *
	 *   For a good connection, status is 0, else a PCP error code;
	 *   challenge contains server-side info (e.g. enabled features)
	 */
	version = __pmDecodeXtendError(pb, &sts, &challenge);
	if (version < 0) {
	    __pmUnpinPDUBuf(pb);
	    return version;
	}
	if (sts < 0) {
	    __pmUnpinPDUBuf(pb);
	    return sts;
	}

	if (version == PDU_VERSION2) {
	    __pmPDUInfo		pduinfo;
	    __pmVersionCred	handshake;
	    int			pduflags = 0;

	    pduinfo = __ntohpmPDUInfo(*(__pmPDUInfo *)&challenge);

	    if (pduinfo.features & PDU_FLAG_CREDS_REQD)
		/*
		 * This is a mandatory connection feature - pmcd must be
		 * sent user credential information one way or another -
		 * i.e. via SASL2 authentication, or AF_UNIX peer creds.
		 */
		pduflags |= PDU_FLAG_CREDS_REQD;

	    if (ctxflags) {
		/*
		 * If an optional connection feature (e.g. encryption) is
		 * desired, the pmcd that we're talking to must advertise
		 * support for the feature.  And if it did, the client in
		 * turn must request it be enabled (now, via pduflags).
		 */
		if (ctxflags & (PM_CTXFLAG_SECURE|PM_CTXFLAG_RELAXED)) {
		    if (pduinfo.features & PDU_FLAG_SECURE) {
			pduflags |= PDU_FLAG_SECURE;
			/*
			 * Determine whether the server can send an ACK for a
			 * secure connection request. We can still connect
			 * whether it does or not, but we need to know the
			 * protocol.
			 */
			if (pduinfo.features & PDU_FLAG_SECURE_ACK)
			    pduflags |= PDU_FLAG_SECURE_ACK;
		    } else if (ctxflags & PM_CTXFLAG_SECURE) {
			__pmUnpinPDUBuf(pb);
			return -EOPNOTSUPP;
		    }
		}
		if (ctxflags & PM_CTXFLAG_COMPRESS) {
		    if (pduinfo.features & PDU_FLAG_COMPRESS)
			pduflags |= PDU_FLAG_COMPRESS;
		    else {
			__pmUnpinPDUBuf(pb);
			return -EOPNOTSUPP;
		    }
		}
		if (ctxflags & PM_CTXFLAG_AUTH) {
		    if (pduinfo.features & PDU_FLAG_AUTH)
			pduflags |= PDU_FLAG_AUTH;
		    else {
			__pmUnpinPDUBuf(pb);
			return -EOPNOTSUPP;
		    }
		}
	    }

	    /*
	     * Negotiate connection version and features (via creds PDU)
	     */
	    if ((ok = __pmSetVersionIPC(fd, version)) < 0) {
		__pmUnpinPDUBuf(pb);
		return ok;
	    }

	    memset(&handshake, 0, sizeof(handshake));
	    handshake.c_type = CVERSION;
	    handshake.c_version = PDU_VERSION;
	    handshake.c_flags = pduflags;

	    sts = __pmSendCreds(fd, (int)getpid(), 1, (__pmCred *)&handshake);

	    /*
	     * At this point we know caller wants to set channel options and
	     * pmcd supports them so go ahead and update the socket now (this
	     * completes the SSL handshake in encrypting mode, authentication
	     * via SASL, and/or enabling compression in NSS).
	     */
	    if (sts >= 0 && pduflags)
		sts = __pmSecureClientHandshake(fd, pduflags, hostname, attrs);
	}
	else
	    sts = PM_ERR_IPC;
    }
    else if (sts != PM_ERR_TIMEOUT)
	sts = PM_ERR_IPC;

    if (pinpdu > 0)
	__pmUnpinPDUBuf(pb);

    return sts;
}
Example #4
0
File: libpcp.c Project: Aconex/pcp
int
__pmLogChkLabel(__pmLogCtl *lcp, FILE *f, __pmLogLabel *lp, int vol)
{
    int		len;
    int		version = UNKNOWN_VERSION;
    int		xpectlen = sizeof(__pmLogLabel) + 2 * sizeof(len);
    int		n;

    if (vol >= 0 && vol < lcp->l_numseen && lcp->l_seen[vol]) {
	/* FastPath, cached result of previous check for this volume */
	fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET);
	return 0;
    }

    if (vol >= 0 && vol >= lcp->l_numseen) {
	lcp->l_seen = (int *)realloc(lcp->l_seen, (vol+1)*(int)sizeof(lcp->l_seen[0]));
	if (lcp->l_seen == NULL)
	    lcp->l_numseen = 0;
	else {
	    int 	i;
	    for (i = lcp->l_numseen; i < vol; i++)
		lcp->l_seen[i] = 0;
	    lcp->l_numseen = vol+1;
	}
    }

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_LOG)
	fprintf(stderr, "__pmLogChkLabel: fd=%d vol=%d", fileno(f), vol);
#endif

    fseek(f, (long)0, SEEK_SET);
    n = (int)fread(&len, 1, sizeof(len), f);
    len = ntohl(len);
    if (n != sizeof(len) || len != xpectlen) {
	if (feof(f)) {
	    clearerr(f);
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_LOG)
		fprintf(stderr, " file is empty\n");
#endif
	    return PM_ERR_NODATA;
	}
	else {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_LOG)
		fprintf(stderr, " header read -> %d (expect %d) or bad header len=%d (expected %d)\n",
		    n, (int)sizeof(len), len, xpectlen);
#endif
	    if (ferror(f)) {
		clearerr(f);
		return -errno;
	    }
	    else
		return PM_ERR_LABEL;
	}
    }

    if ((n = (int)fread(lp, 1, sizeof(__pmLogLabel), f)) != sizeof(__pmLogLabel)) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_LOG)
	    fprintf(stderr, " bad label len=%d: expected %d\n",
		n, (int)sizeof(__pmLogLabel));
#endif
	if (ferror(f)) {
	    clearerr(f);
	    return -errno;
	}
	else
	    return PM_ERR_LABEL;
    }
    else {
	/* swab internal log label */
	lp->ill_magic = ntohl(lp->ill_magic);
	lp->ill_pid = ntohl(lp->ill_pid);
	lp->ill_start.tv_sec = ntohl(lp->ill_start.tv_sec);
	lp->ill_start.tv_usec = ntohl(lp->ill_start.tv_usec);
	lp->ill_vol = ntohl(lp->ill_vol);
    }

    n = (int)fread(&len, 1, sizeof(len), f);
    len = ntohl(len);
    if (n != sizeof(len) || len != xpectlen) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_LOG)
	    fprintf(stderr, " trailer read -> %d (expect %d) or bad trailer len=%d (expected %d)\n",
		n, (int)sizeof(len), len, xpectlen);
#endif
	if (ferror(f)) {
	    clearerr(f);
	    return -errno;
	}
	else
	    return PM_ERR_LABEL;
    }

    version = lp->ill_magic & 0xff;
    if ((lp->ill_magic & 0xffffff00) != PM_LOG_MAGIC ||
	(version != PM_LOG_VERS01 && version != PM_LOG_VERS02) ||
	lp->ill_vol != vol) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_LOG)
	    fprintf(stderr, " version %d not supported\n", version);
#endif
	return PM_ERR_LABEL;
    }
    else {
	if (__pmSetVersionIPC(fileno(f), version) < 0)
	    return -errno;
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_LOG)
	    fprintf(stderr, " [magic=%8x version=%d vol=%d pid=%d host=%s]\n",
		lp->ill_magic, version, lp->ill_vol, (int)lp->ill_pid, lp->ill_hostname);
#endif
    }

    if (vol >= 0 && vol < lcp->l_numseen)
	lcp->l_seen[vol] = 1;

    return version;
}