Esempio n. 1
0
AJ_Status AJ_PeerHandleExchangeGUIDsReply(AJ_Message* msg)
{
    AJ_Status status;
    const char* guidStr;
    AJ_GUID remoteGuid;
    uint32_t version;
    char nul = '\0';

    status = AJ_UnmarshalArgs(msg, "su", &guidStr, &version);
    if (status != AJ_OK) {
        return status;
    }
    if (version != REQUIRED_AUTH_VERSION) {
        PeerAuthComplete(AJ_ERR_SECURITY);
        return AJ_OK;
    }
    AJ_GUID_FromString(&remoteGuid, guidStr);
    /*
     * Two name mappings to add, the well known name, and the unique name from the message.
     */
    AJ_GUID_AddNameMapping(&remoteGuid, msg->sender, authContext.peerName);
    /*
     * Remember which peer is being authenticated
     */
    authContext.peerGuid = AJ_GUID_Find(msg->sender);
    /*
     * Initialize SASL state machine
     */
    AJ_SASL_InitContext(&authContext.sasl, authMechanisms, AJ_AUTH_RESPONDER, msg->bus->pwdCallback);
    /*
     * Start the authentication conversation
     */
    status = AuthResponse(msg, &nul);
    if (status != AJ_OK) {
        PeerAuthComplete(status);
    }
    return status;
}
Esempio n. 2
0
AJ_Status AJ_Authenticate(AJ_BusAttachment* bus)
{
    AJ_Status status = AJ_OK;
    AJ_SASL_Context sasl;

    /*
     * Send initial NUL byte
     */
    bus->sock.tx.writePtr[0] = 0;
    bus->sock.tx.writePtr += 1;
    status = bus->sock.tx.send(&bus->sock.tx);
    if (status != AJ_OK) {
        AJ_InfoPrintf(("AJ_Authenticate(): status=%s\n", AJ_StatusText(status)));
        goto ExitConnect;
    }
    AJ_SASL_InitContext(&sasl, mechList, AJ_AUTH_RESPONDER, busAuthPwdFunc, FALSE);
    while (TRUE) {
        status = AuthAdvance(&sasl, &bus->sock.rx, &bus->sock.tx);
        if ((status != AJ_OK) || (sasl.state == AJ_SASL_FAILED)) {
            break;
        }
        if (sasl.state == AJ_SASL_AUTHENTICATED) {
            status = SendHello(bus);
            break;
        }
    }
    if (status == AJ_OK) {
        AJ_Message helloResponse;
        status = AJ_UnmarshalMsg(bus, &helloResponse, 5000);
        if (status == AJ_OK) {
            /*
             * The only error we might get is a timeout
             */
            if (helloResponse.hdr->msgType == AJ_MSG_ERROR) {
                status = AJ_ERR_TIMEOUT;
            } else {
                AJ_Arg arg;
                status = AJ_UnmarshalArg(&helloResponse, &arg);
                if (status == AJ_OK) {
                    if (arg.len >= (sizeof(bus->uniqueName) - 1)) {
                        AJ_ErrPrintf(("AJ_Authenticate(): AJ_ERR_RESOURCES\n"));
                        status = AJ_ERR_RESOURCES;
                    } else {
                        memcpy(bus->uniqueName, arg.val.v_string, arg.len);
                        bus->uniqueName[arg.len] = '\0';
                    }
                }
            }
            AJ_CloseMsg(&helloResponse);

            // subscribe to the signal NameOwnerChanged and wait for the response
            status = AJ_BusSetSignalRule(bus, "type='signal',member='NameOwnerChanged',interface='org.freedesktop.DBus'", AJ_BUS_SIGNAL_ALLOW);

            if (status == AJ_OK) {
                uint8_t found_reply = FALSE;
                AJ_Message msg;
                AJ_Time timer;
                AJ_InitTimer(&timer);

                while (found_reply == FALSE && AJ_GetElapsedTime(&timer, TRUE) < 3000) {
                    status = AJ_UnmarshalMsg(bus, &msg, 3000);
                    if (status == AJ_OK) {
                        switch (msg.msgId) {
                        case AJ_REPLY_ID(AJ_METHOD_ADD_MATCH):
                            found_reply = TRUE;
                            break;

                        default:
                            // ignore everything else
                            AJ_BusHandleBusMessage(&msg);
                            break;
                        }

                        AJ_CloseMsg(&msg);
                    }
                }
            }
        }
    }

ExitConnect:

    if (status != AJ_OK) {
        AJ_InfoPrintf(("AJ_Authenticate(): status=%s\n", AJ_StatusText(status)));
    }
    return status;
}
Esempio n. 3
0
AJ_Status AJ_PeerHandleAuthChallenge(AJ_Message* msg, AJ_Message* reply)
{
    AJ_Status status;
    AJ_Arg arg;
    char* buf = NULL;
    const AJ_GUID* peerGuid = AJ_GUID_Find(msg->sender);

    /*
     * We expect to know the GUID of the sender
     */
    if (!peerGuid) {
        return AJ_MarshalErrorMsg(msg, reply, AJ_ErrRejected);
    }
    /*
     * Check for an authentication conversation in progress with a different peer
     */
    if (authContext.peerGuid && (authContext.peerGuid != peerGuid)) {
        /*
         * Reject the request if the existing conversation has not expired
         */
        if (AJ_GetElapsedTime(&authContext.timer, TRUE) < MAX_AUTH_TIME) {
            return AJ_MarshalErrorMsg(msg, reply, AJ_ErrRejected);
        }
        memset(&authContext, 0, sizeof(AuthContext));
    }
    if (authContext.sasl.state == AJ_SASL_IDLE) {
        /*
         * Remember which peer is being authenticated and initialize the timeout timer
         */
        authContext.peerGuid = peerGuid;
        AJ_InitTimer(&authContext.timer);
        /*
         * Initialize SASL state machine
         */
        AJ_SASL_InitContext(&authContext.sasl, authMechanisms, AJ_AUTH_CHALLENGER, msg->bus->pwdCallback);
    }
    if (AJ_UnmarshalArg(msg, &arg) != AJ_OK) {
        goto FailAuth;
    }
    /*
     * Need a short-lived buffer to compose the response
     */
    buf = (char*)AJ_Malloc(AUTH_BUF_LEN);
    if (!buf) {
        status = AJ_ERR_RESOURCES;
        goto FailAuth;
    }
    status = AJ_SASL_Advance(&authContext.sasl, (char*)arg.val.v_string, buf, AUTH_BUF_LEN);
    if (status != AJ_OK) {
        goto FailAuth;
    }
    AJ_MarshalReplyMsg(msg, reply);
    AJ_MarshalArgs(reply, "s", buf);
    AJ_Free(buf);
    if (authContext.sasl.state == AJ_SASL_AUTHENTICATED) {
        status = authContext.sasl.mechanism->Final(peerGuid);
        memset(&authContext, 0, sizeof(AuthContext));
    }
    return status;

FailAuth:

    AJ_Free(buf);
    /*
     * Clear current authentication context then return an error response
     */
    if (authContext.sasl.mechanism) {
        authContext.sasl.mechanism->Final(peerGuid);
    }
    memset(&authContext, 0, sizeof(AuthContext));
    return AJ_MarshalErrorMsg(msg, reply, AJ_ErrSecurityViolation);
}
Esempio n. 4
0
AJ_Status AJ_Connect(AJ_BusAttachment* bus, const char* serviceName, uint32_t timeout)
{
    AJ_Status status;
    AJ_SASL_Context sasl;
    AJ_Service service;
    /*
     * Clear the bus struct
     */
    memset(bus, 0, sizeof(AJ_BusAttachment));
    /*
     * Clear stale name->GUID mappings
     */
    AJ_GUID_ClearNameMap();
    /*
     * Host-specific network bring-up procedure. This includes establishing a connection to the
     * network and initializing the I/O buffers.
     */
    status = AJ_Net_Up();
    if (status != AJ_OK) {
        return status;
    }
    /*
     * Discover a daemon or service to connect to
     */
    if (!serviceName) {
        serviceName = daemonService;
    }
#if AJ_CONNECT_LOCALHOST
    service.ipv4port = 9955;
#if HOST_IS_LITTLE_ENDIAN
    service.ipv4 = 0x0100007F; // 127.0.0.1
#endif
#if HOST_IS_BIG_ENDIAN
    service.ipv4 = 0x7f000001; // 127.0.0.1
#endif
    service.addrTypes = AJ_ADDR_IPV4;
#elif defined ARDUINO
    service.ipv4port = 9955;
    service.ipv4 = 0x6501A8C0; // 192.168.1.101
    service.addrTypes = AJ_ADDR_IPV4;
    status = AJ_Discover(serviceName, &service, timeout);
    if (status != AJ_OK) {
        goto ExitConnect;
    }
#elif defined AJ_SERIAL_CONNECTION
    // don't bother with discovery, we are connected to a daemon.
#else
    status = AJ_Discover(serviceName, &service, timeout);
    if (status != AJ_OK) {
        goto ExitConnect;
    }
#endif
    status = AJ_Net_Connect(&bus->sock, service.ipv4port, service.addrTypes & AJ_ADDR_IPV4, &service.ipv4);
    if (status != AJ_OK) {
        goto ExitConnect;
    }
    /*
     * Send initial NUL byte
     */
    bus->sock.tx.writePtr[0] = 0;
    bus->sock.tx.writePtr += 1;
    status = bus->sock.tx.send(&bus->sock.tx);
    if (status != AJ_OK) {
        goto ExitConnect;
    }
    AJ_SASL_InitContext(&sasl, mechList, AJ_AUTH_RESPONDER, busAuthPwdFunc);
    while (TRUE) {
        status = AuthAdvance(&sasl, &bus->sock.rx, &bus->sock.tx);
        if ((status != AJ_OK) || (sasl.state == AJ_SASL_FAILED)) {
            break;
        }
        if (sasl.state == AJ_SASL_AUTHENTICATED) {
            status = SendHello(bus);
            break;
        }
    }
    if (status == AJ_OK) {
        AJ_Message helloResponse;
        status = AJ_UnmarshalMsg(bus, &helloResponse, 5000);
        if (status == AJ_OK) {
            /*
             * The only error we might get is a timeout
             */
            if (helloResponse.hdr->msgType == AJ_MSG_ERROR) {
                status = AJ_ERR_TIMEOUT;
            } else {
                AJ_Arg arg;
                status = AJ_UnmarshalArg(&helloResponse, &arg);
                if (status == AJ_OK) {
                    if (arg.len >= (sizeof(bus->uniqueName) - 1)) {
                        status = AJ_ERR_RESOURCES;
                    } else {
                        memcpy(bus->uniqueName, arg.val.v_string, arg.len);
                        bus->uniqueName[arg.len] = '\0';
                    }
                }
            }
            AJ_CloseMsg(&helloResponse);
        }
    }

ExitConnect:

    if (status != AJ_OK) {
        AJ_Printf("AllJoyn connect failed %d\n", status);
        AJ_Disconnect(bus);
    }
    return status;
}