static AJ_Status AuthAdvance(AJ_SASL_Context* context, AJ_IOBuffer* rxBuf, AJ_IOBuffer* txBuf) { AJ_Status status = AJ_OK; AJ_InfoPrintf(("AuthAdvance(context=0x%p, rxBuf=0x%p, txBuf=0x%p)\n", context, rxBuf, txBuf)); if (context->state != AJ_SASL_SEND_AUTH_REQ) { /* * All the authentication messages end in a CR/LF so read until we get a newline */ while ((AJ_IO_BUF_AVAIL(rxBuf) == 0) || (*(rxBuf->writePtr - 1) != '\n')) { status = rxBuf->recv(rxBuf, AJ_IO_BUF_SPACE(rxBuf), 3500); if (status != AJ_OK) { break; } } } if (status == AJ_OK) { uint32_t inLen = AJ_IO_BUF_AVAIL(rxBuf); *rxBuf->writePtr = '\0'; status = AJ_SASL_Advance(context, (char*)rxBuf->readPtr, (char*)txBuf->writePtr, AJ_IO_BUF_SPACE(txBuf)); if (status == AJ_OK) { rxBuf->readPtr += inLen; txBuf->writePtr += strlen((char*)txBuf->writePtr); status = txBuf->send(txBuf); } } return status; }
static AJ_Status AuthResponse(AJ_Message* msg, char* inStr) { AJ_Status status; char* buf; if (authContext.sasl.state == AJ_SASL_AUTHENTICATED) { return GenSessionKey(msg); } /* * Need a short-lived buffer to compose the response */ buf = (char*)AJ_Malloc(AUTH_BUF_LEN); if (!buf) { status = AJ_ERR_RESOURCES; } else { status = AJ_SASL_Advance(&authContext.sasl, inStr, buf, AUTH_BUF_LEN); if (status == AJ_OK) { AJ_Message call; AJ_MarshalMethodCall(msg->bus, &call, AJ_METHOD_AUTH_CHALLENGE, msg->sender, 0, AJ_NO_FLAGS, AUTH_CALL_TIMEOUT); AJ_MarshalArgs(&call, "s", buf); status = AJ_DeliverMsg(&call); } AJ_Free(buf); } /* * If there was an error finalize the auth mechanism */ if (status != AJ_OK) { if (authContext.sasl.mechanism) { authContext.sasl.mechanism->Final(authContext.peerGuid); } /* * Report authentication failure to application */ if (status != AJ_OK) { PeerAuthComplete(status); } } return status; }
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); }