Example #1
0
unsigned int
__pmServerGetFeaturesFromPDU(__pmPDU *pb)
{
    int         version;
    int         challenge;
    __pmPDUInfo         pduinfo;
    int		sts;
    unsigned int server_features=0;

    version = __pmDecodeXtendError(pb, &sts, &challenge);

    if( version >= 0 && version == PDU_VERSION2  && sts >=0 ){
	pduinfo = __ntohpmPDUInfo(*(__pmPDUInfo *)&challenge);
	server_features = pduinfo.features;
    }
    
    return server_features;
}
Example #2
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;
}