diff --git a/src/internal.c b/src/internal.c index 1a341b37..9abd8af8 100644 --- a/src/internal.c +++ b/src/internal.c @@ -138,6 +138,9 @@ const char* GetErrorString(int err) case WS_INVALID_CHANID: return "peer requested invalid channel id"; + case WS_CRYPTO_FAILED: + return "crypto action failed"; + default: return "Unknown error code"; } @@ -566,11 +569,21 @@ static int SendBuffered(WOLFSSH* ssh) static int SendText(WOLFSSH* ssh, const char* text, uint32_t textLen) { - GrowBuffer(&ssh->outputBuffer, textLen, 0); - WMEMCPY(ssh->outputBuffer.buffer, text, textLen); - ssh->outputBuffer.length = textLen; + int ret = WS_SUCCESS; - return SendBuffered(ssh); + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; + + if (ret == WS_SUCCESS) + ret = GrowBuffer(&ssh->outputBuffer, textLen, 0); + + if (ret == WS_SUCCESS) { + WMEMCPY(ssh->outputBuffer.buffer, text, textLen); + ssh->outputBuffer.length = textLen; + ret = SendBuffered(ssh); + } + + return ret; } @@ -1421,50 +1434,71 @@ static int GetString(char* s, uint32_t* sSz, static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData, uint8_t* buf, uint32_t len, uint32_t* idx) { - uint32_t begin = *idx; - WS_UserAuthData_Password* pw = &authData->sf.password; - int ret; + uint32_t begin; + WS_UserAuthData_Password* pw; + int ret = WS_SUCCESS; - authData->type = WOLFSSH_USERAUTH_PASSWORD; - ret = GetBoolean(&pw->hasNewPassword, buf, len, &begin); - ret = GetUint32(&pw->passwordSz, buf, len, &begin); - pw->password = buf + begin; - begin += pw->passwordSz; + WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPassword()"); - if (pw->hasNewPassword) { - /* Skip the password change. Maybe error out since we aren't - * supporting password changes at this time. */ - ret = GetUint32(&pw->newPasswordSz, buf, len, &begin); - pw->newPassword = buf + begin; - begin += pw->newPasswordSz; - } - else { - pw->newPassword = NULL; - pw->newPasswordSz = 0; + if (ssh == NULL || authData == NULL || + buf == NULL || len == 0 || idx == NULL) { + + ret = WS_BAD_ARGUMENT; } - if (ssh->ctx->userAuthCb != NULL) { - WLOG(WS_LOG_DEBUG, "DUARPW: Calling the userauth callback"); - ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD, - authData, ssh->userAuthCtx); - if (ret == WOLFSSH_USERAUTH_SUCCESS) { - WLOG(WS_LOG_DEBUG, "DUARPW: password check successful"); - ssh->clientState = CLIENT_USERAUTH_DONE; - } - else { - WLOG(WS_LOG_DEBUG, "DUARPW: password check failed"); - if (ret != WOLFSSH_USERAUTH_SUCCESS) { - return SendUserAuthFailure(ssh, 0); + if (ret == WS_SUCCESS) { + begin = *idx; + pw = &authData->sf.password; + authData->type = WOLFSSH_USERAUTH_PASSWORD; + ret = GetBoolean(&pw->hasNewPassword, buf, len, &begin); + } + + if (ret == WS_SUCCESS) + ret = GetUint32(&pw->passwordSz, buf, len, &begin); + + if (ret == WS_SUCCESS) { + pw->password = buf + begin; + begin += pw->passwordSz; + + if (pw->hasNewPassword) { + /* Skip the password change. Maybe error out since we aren't + * supporting password changes at this time. */ + ret = GetUint32(&pw->newPasswordSz, buf, len, &begin); + if (ret == WS_SUCCESS) { + pw->newPassword = buf + begin; + begin += pw->newPasswordSz; } } - } - else { - WLOG(WS_LOG_DEBUG, "DUARPW: No user auth callback"); - return SendUserAuthFailure(ssh, 0); + else { + pw->newPassword = NULL; + pw->newPasswordSz = 0; + } + + if (ssh->ctx->userAuthCb != NULL) { + WLOG(WS_LOG_DEBUG, "DUARPW: Calling the userauth callback"); + ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD, + authData, ssh->userAuthCtx); + if (ret == WOLFSSH_USERAUTH_SUCCESS) { + WLOG(WS_LOG_DEBUG, "DUARPW: password check successful"); + ssh->clientState = CLIENT_USERAUTH_DONE; + ret = WS_SUCCESS; + } + else { + WLOG(WS_LOG_DEBUG, "DUARPW: password check failed"); + ret = SendUserAuthFailure(ssh, 0); + } + } + else { + WLOG(WS_LOG_DEBUG, "DUARPW: No user auth callback"); + ret = SendUserAuthFailure(ssh, 0); + } } - *idx = begin; - return WS_SUCCESS; + if (ret == WS_SUCCESS) + *idx = begin; + + WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPassword(), ret = %d", ret); + return ret; } @@ -1481,47 +1515,85 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, uint8_t* e; uint32_t eSz = 0; uint32_t i = 0; - int ret; + int ret = WS_SUCCESS; WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestRsa()"); + + if (ssh == NULL || pk == NULL || digest == NULL || digestSz == 0) + ret = WS_BAD_ARGUMENT; + /* First check that the public key's type matches the one we are * expecting. */ - GetUint32(&publicKeyTypeSz, pk->publicKey, pk->publicKeySz, &i); - publicKeyType = pk->publicKey + i; - i += publicKeyTypeSz; - if (publicKeyTypeSz != pk->publicKeyTypeSz && - WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) { + if (ret == WS_SUCCESS) + ret = GetUint32(&publicKeyTypeSz, pk->publicKey, pk->publicKeySz, &i); - WLOG(WS_LOG_DEBUG, "Public Key's type does not match public key type"); - return WS_INVALID_ALGO_ID; - } - GetUint32(&eSz, pk->publicKey, pk->publicKeySz, &i); - e = pk->publicKey + i; - i += eSz; - GetUint32(&nSz, pk->publicKey, pk->publicKeySz, &i); - n = pk->publicKey + i; + if (ret == WS_SUCCESS) { + publicKeyType = pk->publicKey + i; + i += publicKeyTypeSz; + if (publicKeyTypeSz != pk->publicKeyTypeSz && + WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) { - wc_InitRsaKey(&key, ssh->ctx->heap); - ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, &key); - - i = 0; - /* First check that the signature's public key type matches the one - * we are expecting. */ - GetUint32(&publicKeyTypeSz, pk->publicKey, pk->publicKeySz, &i); - publicKeyType = pk->publicKey + i; - i += publicKeyTypeSz; - if (publicKeyTypeSz != pk->publicKeyTypeSz && - WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) { - - WLOG(WS_LOG_DEBUG, "Signature's type does not match public key type"); - return WS_INVALID_ALGO_ID; + WLOG(WS_LOG_DEBUG, + "Public Key's type does not match public key type"); + ret = WS_INVALID_ALGO_ID; + } + } + + if (ret == WS_SUCCESS) + ret = GetUint32(&eSz, pk->publicKey, pk->publicKeySz, &i); + + if (ret == WS_SUCCESS) { + e = pk->publicKey + i; + i += eSz; + ret = GetUint32(&nSz, pk->publicKey, pk->publicKeySz, &i); + } + + if (ret == WS_SUCCESS) { + n = pk->publicKey + i; + + wc_InitRsaKey(&key, ssh->ctx->heap); + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, &key); + if (ret != 0) { + WLOG(WS_LOG_DEBUG, "Could not decode public key"); + ret = WS_CRYPTO_FAILED; + } + } + + if (ret == WS_SUCCESS) { + i = 0; + /* First check that the signature's public key type matches the one + * we are expecting. */ + ret = GetUint32(&publicKeyTypeSz, pk->publicKey, pk->publicKeySz, &i); + } + + if (ret == WS_SUCCESS) { + publicKeyType = pk->publicKey + i; + i += publicKeyTypeSz; + + if (publicKeyTypeSz != pk->publicKeyTypeSz && + WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) { + + WLOG(WS_LOG_DEBUG, + "Signature's type does not match public key type"); + ret = WS_INVALID_ALGO_ID; + } + } + + if (ret == WS_SUCCESS) + ret = GetUint32(&nSz, pk->signature, pk->signatureSz, &i); + + if (ret == WS_SUCCESS) { + n = pk->signature + i; + ret = wc_RsaSSL_Verify(n, nSz, digest, digestSz, &key); + if (ret <= 0) { + WLOG(WS_LOG_DEBUG, "Could not verify signature"); + ret = WS_CRYPTO_FAILED; + } } - GetUint32(&nSz, pk->signature, pk->signatureSz, &i); - n = pk->signature + i; - ret = wc_RsaSSL_Verify(n, nSz, digest, digestSz, &key); wc_FreeRsaKey(&key); + WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestRsa(), ret = %d", ret); return ret; } @@ -1530,112 +1602,139 @@ static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, uint8_t* buf, uint32_t len, uint32_t* idx) { - uint32_t begin = *idx; - WS_UserAuthData_PublicKey* pk = &authData->sf.publicKey; + uint32_t begin; + WS_UserAuthData_PublicKey* pk; int ret = WS_SUCCESS; WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPublicKey()"); - authData->type = WOLFSSH_USERAUTH_PUBLICKEY; - GetBoolean(&pk->hasSignature, buf, len, &begin); - GetUint32(&pk->publicKeyTypeSz, buf, len, &begin); - pk->publicKeyType = buf + begin; - begin += pk->publicKeyTypeSz; - GetUint32(&pk->publicKeySz, buf, len, &begin); - pk->publicKey = buf + begin; - begin += pk->publicKeySz; + if (ssh == NULL || authData == NULL || + buf == NULL || len == 0 || idx == NULL) { - if (pk->hasSignature) { - GetUint32(&pk->signatureSz, buf, len, &begin); - pk->signature = buf + begin; - begin += pk->signatureSz; - } - else { - pk->signature = NULL; - pk->signatureSz = 0; + ret = WS_BAD_ARGUMENT; } - *idx = begin; - - if (ssh->ctx->userAuthCb != NULL) { - WLOG(WS_LOG_DEBUG, "DUARPK: Calling the userauth callback"); - ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY, - authData, ssh->userAuthCtx); - WLOG(WS_LOG_DEBUG, "DUARPK: callback result = %d", ret); - if (ret != WOLFSSH_USERAUTH_SUCCESS) { - return SendUserAuthFailure(ssh, 0); - } - } - else { - WLOG(WS_LOG_DEBUG, "DUARPK: no userauth callback set"); - return SendUserAuthFailure(ssh, 0); + if (ret == WS_SUCCESS) { + begin = *idx; + pk = &authData->sf.publicKey; + authData->type = WOLFSSH_USERAUTH_PUBLICKEY; + ret = GetBoolean(&pk->hasSignature, buf, len, &begin); } - if (pk->signature == NULL) { - WLOG(WS_LOG_DEBUG, "DUARPK: Send the PK OK"); - ret = SendUserAuthPkOk(ssh, pk->publicKeyType, pk->publicKeyTypeSz, - pk->publicKey, pk->publicKeySz); + if (ret == WS_SUCCESS) + ret = GetUint32(&pk->publicKeyTypeSz, buf, len, &begin); + + if (ret == WS_SUCCESS) { + pk->publicKeyType = buf + begin; + begin += pk->publicKeyTypeSz; + ret = GetUint32(&pk->publicKeySz, buf, len, &begin); } - else { - uint8_t checkDigest[MAX_ENCODED_SIG_SZ]; - uint32_t checkDigestSz = sizeof(checkDigest); - uint8_t encDigest[MAX_ENCODED_SIG_SZ]; - uint32_t encDigestSz; - uint8_t pkTypeId; - pkTypeId = NameToId((char*)pk->publicKeyType, pk->publicKeyTypeSz); + if (ret == WS_SUCCESS) { + pk->publicKey = buf + begin; + begin += pk->publicKeySz; - if (pkTypeId == ID_SSH_RSA) - ret = DoUserAuthRequestRsa(ssh, pk, checkDigest, checkDigestSz); - else - ret = WS_INVALID_ALGO_ID; - - if (ret > 0) { - checkDigestSz = (uint32_t)ret; - ret = WS_SUCCESS; - } - - { - Sha sha; - uint8_t digest[SHA_DIGEST_SIZE]; - - wc_InitSha(&sha); - c32toa(ssh->sessionIdSz, digest); - wc_ShaUpdate(&sha, digest, UINT32_SZ); - wc_ShaUpdate(&sha, ssh->sessionId, ssh->sessionIdSz); - digest[0] = MSGID_USERAUTH_REQUEST; - wc_ShaUpdate(&sha, digest, MSG_ID_SZ); - - /* The rest of the fields in the signature are already - * in the buffer. Just need to account for the sizes. */ - wc_ShaUpdate(&sha, pk->dataToSign, - authData->usernameSz + authData->serviceNameSz + - authData->authNameSz + BOOLEAN_SZ + - pk->publicKeyTypeSz + pk->publicKeySz + - (UINT32_SZ * 5)); - wc_ShaFinal(&sha, digest); - - encDigestSz = wc_EncodeSignature(encDigest, digest, - SHA_DIGEST_SIZE, SHAh); - } - - { - volatile int compare; - volatile int sizeCompare; - - compare = ConstantCompare(encDigest, checkDigest, encDigestSz); - sizeCompare = encDigestSz != checkDigestSz; - - if (compare || sizeCompare || ret < 0) { - WLOG(WS_LOG_DEBUG, "DUARPK: signature compare failure"); - return SendUserAuthFailure(ssh, 0); + if (pk->hasSignature) { + ret = GetUint32(&pk->signatureSz, buf, len, &begin); + if (ret == WS_SUCCESS) { + pk->signature = buf + begin; + begin += pk->signatureSz; } + else + goto onError; + } + else { + pk->signature = NULL; + pk->signatureSz = 0; + } + + *idx = begin; + + if (ssh->ctx->userAuthCb != NULL) { + WLOG(WS_LOG_DEBUG, "DUARPK: Calling the userauth callback"); + ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY, + authData, ssh->userAuthCtx); + WLOG(WS_LOG_DEBUG, "DUARPK: callback result = %d", ret); + if (ret == WOLFSSH_USERAUTH_SUCCESS) + ret = WS_SUCCESS; else { - ssh->clientState = CLIENT_USERAUTH_DONE; + ret = SendUserAuthFailure(ssh, 0); + goto onError; + } + } + else { + WLOG(WS_LOG_DEBUG, "DUARPK: no userauth callback set"); + ret = SendUserAuthFailure(ssh, 0); + goto onError; + } + } + + if (ret == WS_SUCCESS) { + if (pk->signature == NULL) { + WLOG(WS_LOG_DEBUG, "DUARPK: Send the PK OK"); + ret = SendUserAuthPkOk(ssh, pk->publicKeyType, pk->publicKeyTypeSz, + pk->publicKey, pk->publicKeySz); + } + else { + uint8_t checkDigest[MAX_ENCODED_SIG_SZ]; + uint32_t checkDigestSz = sizeof(checkDigest); + uint8_t encDigest[MAX_ENCODED_SIG_SZ]; + uint32_t encDigestSz; + uint8_t pkTypeId; + + pkTypeId = NameToId((char*)pk->publicKeyType, pk->publicKeyTypeSz); + + if (pkTypeId == ID_SSH_RSA) + ret = DoUserAuthRequestRsa(ssh, pk, checkDigest, checkDigestSz); + else + ret = WS_INVALID_ALGO_ID; + + if (ret > 0) { + checkDigestSz = (uint32_t)ret; + ret = WS_SUCCESS; + } + + if (ret == WS_SUCCESS) { + Sha sha; + uint8_t digest[SHA_DIGEST_SIZE]; + volatile int compare; + volatile int sizeCompare; + + wc_InitSha(&sha); + c32toa(ssh->sessionIdSz, digest); + wc_ShaUpdate(&sha, digest, UINT32_SZ); + wc_ShaUpdate(&sha, ssh->sessionId, ssh->sessionIdSz); + digest[0] = MSGID_USERAUTH_REQUEST; + wc_ShaUpdate(&sha, digest, MSG_ID_SZ); + + /* The rest of the fields in the signature are already + * in the buffer. Just need to account for the sizes. */ + wc_ShaUpdate(&sha, pk->dataToSign, + authData->usernameSz + authData->serviceNameSz + + authData->authNameSz + BOOLEAN_SZ + + pk->publicKeyTypeSz + pk->publicKeySz + + (UINT32_SZ * 5)); + wc_ShaFinal(&sha, digest); + + encDigestSz = wc_EncodeSignature(encDigest, digest, + SHA_DIGEST_SIZE, SHAh); + + compare = ConstantCompare(encDigest, checkDigest, encDigestSz); + sizeCompare = encDigestSz != checkDigestSz; + + if (compare || sizeCompare || ret < 0) { + WLOG(WS_LOG_DEBUG, "DUARPK: signature compare failure"); + ret = SendUserAuthFailure(ssh, 0); + } + else { + ssh->clientState = CLIENT_USERAUTH_DONE; + } } } } +onError: + WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPublicKey(), ret = %d", ret); return ret; } @@ -1643,39 +1742,59 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData, static int DoUserAuthRequest(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) { - uint32_t begin = *idx; - int ret; + uint32_t begin; + int ret = WS_SUCCESS; uint8_t authNameId; WS_UserAuthData authData; - WMEMSET(&authData, 0, sizeof(authData)); + WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequest()"); - GetUint32(&authData.usernameSz, buf, len, &begin); - authData.username = buf + begin; - begin += authData.usernameSz; - GetUint32(&authData.serviceNameSz, buf, len, &begin); - authData.serviceName = buf + begin; - begin += authData.serviceNameSz; + if (ssh == NULL || buf == NULL || len == 0 || idx == NULL) + ret = WS_BAD_ARGUMENT; - GetUint32(&authData.authNameSz, buf, len, &begin); - authData.authName = buf + begin; - begin += authData.authNameSz; - authNameId = NameToId((char*)authData.authName, authData.authNameSz); - if (authNameId == ID_USERAUTH_PASSWORD) - ret = DoUserAuthRequestPassword(ssh, &authData, buf, len, &begin); - else if (authNameId == ID_USERAUTH_PUBLICKEY) { - authData.sf.publicKey.dataToSign = buf + *idx; - ret = DoUserAuthRequestPublicKey(ssh, &authData, buf, len, &begin); - } - else { - WLOG(WS_LOG_DEBUG, "invalid userauth type: %s", IdToName(authNameId)); - ret = SendUserAuthFailure(ssh, 0); + if (ret == WS_SUCCESS) { + begin = *idx; + WMEMSET(&authData, 0, sizeof(authData)); + ret = GetUint32(&authData.usernameSz, buf, len, &begin); } - *idx = begin; + if (ret == WS_SUCCESS) { + authData.username = buf + begin; + begin += authData.usernameSz; + ret = GetUint32(&authData.serviceNameSz, buf, len, &begin); + } + + if (ret == WS_SUCCESS) { + authData.serviceName = buf + begin; + begin += authData.serviceNameSz; + + ret = GetUint32(&authData.authNameSz, buf, len, &begin); + } + + if (ret == WS_SUCCESS) { + authData.authName = buf + begin; + begin += authData.authNameSz; + authNameId = NameToId((char*)authData.authName, authData.authNameSz); + + if (authNameId == ID_USERAUTH_PASSWORD) + ret = DoUserAuthRequestPassword(ssh, &authData, buf, len, &begin); + else if (authNameId == ID_USERAUTH_PUBLICKEY) { + authData.sf.publicKey.dataToSign = buf + *idx; + ret = DoUserAuthRequestPublicKey(ssh, &authData, buf, len, &begin); + } + else { + WLOG(WS_LOG_DEBUG, + "invalid userauth type: %s", IdToName(authNameId)); + ret = SendUserAuthFailure(ssh, 0); + } + + *idx = begin; + } + + WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequest(), ret = %d", ret); return ret; } @@ -2323,50 +2442,66 @@ int ProcessClientVersion(WOLFSSH* ssh) int SendServerVersion(WOLFSSH* ssh) { + int ret = WS_SUCCESS; uint32_t sshIdStrSz = (uint32_t)WSTRLEN(sshIdStr); - uint8_t scratch[LENGTH_SZ]; + uint8_t sshIdStrSzFlat[LENGTH_SZ]; - WLOG(WS_LOG_DEBUG, "%s", sshIdStr); - SendText(ssh, sshIdStr, (uint32_t)WSTRLEN(sshIdStr)); - sshIdStrSz -= 2; /* Remove the CRLF */ - c32toa(sshIdStrSz, scratch); - wc_ShaUpdate(&ssh->handshake->hash, scratch, LENGTH_SZ); - wc_ShaUpdate(&ssh->handshake->hash, (const uint8_t*)sshIdStr, sshIdStrSz); + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; - return WS_SUCCESS; + if (ret == WS_SUCCESS) { + WLOG(WS_LOG_DEBUG, "%s", sshIdStr); + ret = SendText(ssh, sshIdStr, (uint32_t)WSTRLEN(sshIdStr)); + } + + if (ret == WS_SUCCESS) { + sshIdStrSz -= 2; /* Remove the CRLF */ + c32toa(sshIdStrSz, sshIdStrSzFlat); + wc_ShaUpdate(&ssh->handshake->hash, sshIdStrSzFlat, LENGTH_SZ); + wc_ShaUpdate(&ssh->handshake->hash, + (const uint8_t*)sshIdStr, sshIdStrSz); + } + + return ret; } static int PreparePacket(WOLFSSH* ssh, uint32_t payloadSz) { - int ret; + int ret = WS_SUCCESS; uint8_t* output; uint32_t outputSz; uint32_t packetSz; uint32_t usedSz; uint8_t paddingSz; - /* Minimum value for paddingSz is 4. */ - paddingSz = ssh->blockSz - - (LENGTH_SZ + PAD_LENGTH_SZ + payloadSz) % ssh->blockSz; - if (paddingSz < 4) - paddingSz += ssh->blockSz; - ssh->paddingSz = paddingSz; - packetSz = PAD_LENGTH_SZ + payloadSz + paddingSz; - outputSz = LENGTH_SZ + packetSz + ssh->macSz; - usedSz = ssh->outputBuffer.length - ssh->outputBuffer.idx; + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; - if ( (ret = GrowBuffer(&ssh->outputBuffer, outputSz, usedSz)) != WS_SUCCESS) - return ret; + if (ret == WS_SUCCESS) { + /* Minimum value for paddingSz is 4. */ + paddingSz = ssh->blockSz - + (LENGTH_SZ + PAD_LENGTH_SZ + payloadSz) % ssh->blockSz; + if (paddingSz < 4) + paddingSz += ssh->blockSz; + ssh->paddingSz = paddingSz; + packetSz = PAD_LENGTH_SZ + payloadSz + paddingSz; + outputSz = LENGTH_SZ + packetSz + ssh->macSz; + usedSz = ssh->outputBuffer.length - ssh->outputBuffer.idx; - ssh->packetStartIdx = ssh->outputBuffer.length; - output = ssh->outputBuffer.buffer + ssh->outputBuffer.length; + ret = GrowBuffer(&ssh->outputBuffer, outputSz, usedSz); + } - /* fill in the packetSz, paddingSz */ - c32toa(packetSz, output); - output[LENGTH_SZ] = paddingSz; + if (ret == WS_SUCCESS) { + ssh->packetStartIdx = ssh->outputBuffer.length; + output = ssh->outputBuffer.buffer + ssh->outputBuffer.length; - ssh->outputBuffer.length += LENGTH_SZ + PAD_LENGTH_SZ; + /* fill in the packetSz, paddingSz */ + c32toa(packetSz, output); + output[LENGTH_SZ] = paddingSz; + + ssh->outputBuffer.length += LENGTH_SZ + PAD_LENGTH_SZ; + } return ret; } @@ -2379,42 +2514,52 @@ static int BundlePacket(WOLFSSH* ssh) uint8_t paddingSz; int ret = WS_SUCCESS; - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; - paddingSz = ssh->paddingSz; + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; - /* Add the padding */ - WLOG(WS_LOG_DEBUG, "BP: paddingSz = %u", paddingSz); - if (ssh->encryptId == ID_NONE) - WMEMSET(output + idx, 0, paddingSz); - else - ret = wc_RNG_GenerateBlock(ssh->rng, output + idx, paddingSz); - idx += paddingSz; - if (ret != WS_SUCCESS) { + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; + paddingSz = ssh->paddingSz; + + /* Add the padding */ + WLOG(WS_LOG_DEBUG, "BP: paddingSz = %u", paddingSz); + if (ssh->encryptId == ID_NONE) + WMEMSET(output + idx, 0, paddingSz); + else if (wc_RNG_GenerateBlock(ssh->rng, output + idx, paddingSz) < 0) + ret = WS_CRYPTO_FAILED; + } + + if (ret == WS_SUCCESS) { + idx += paddingSz; + ret = CreateMac(ssh, ssh->outputBuffer.buffer + ssh->packetStartIdx, + ssh->outputBuffer.length - + ssh->packetStartIdx + paddingSz, + output + idx); + } + else { WLOG(WS_LOG_DEBUG, "BP: failed to add padding"); - return ret; } - ret = CreateMac(ssh, ssh->outputBuffer.buffer + ssh->packetStartIdx, - ssh->outputBuffer.length - ssh->packetStartIdx + paddingSz, - output + idx); - idx += ssh->macSz; - if (ret != WS_SUCCESS) { - WLOG(WS_LOG_DEBUG, "BP: failed to add mac"); - return ret; + if (ret == WS_SUCCESS) { + idx += ssh->macSz; + ret = Encrypt(ssh, + ssh->outputBuffer.buffer + ssh->packetStartIdx, + ssh->outputBuffer.buffer + ssh->packetStartIdx, + ssh->outputBuffer.length - + ssh->packetStartIdx + paddingSz); + } + else { + WLOG(WS_LOG_DEBUG, "BP: failed to generate mac"); } - ret = Encrypt(ssh, - ssh->outputBuffer.buffer + ssh->packetStartIdx, - ssh->outputBuffer.buffer + ssh->packetStartIdx, - ssh->outputBuffer.length - ssh->packetStartIdx + paddingSz); - ssh->outputBuffer.length = idx; - if (ret != WS_SUCCESS) { + if (ret == WS_SUCCESS) + ssh->outputBuffer.length = idx; + else { WLOG(WS_LOG_DEBUG, "BP: failed to encrypt buffer"); - return ret; } - return WS_SUCCESS; + return ret; } @@ -2453,58 +2598,62 @@ int SendKexInit(WOLFSSH* ssh) uint8_t* payload; uint32_t idx = 0; uint32_t payloadSz; + uint8_t payloadSzFlat[LENGTH_SZ]; int ret = WS_SUCCESS; - payloadSz = MSG_ID_SZ + COOKIE_SZ + (LENGTH_SZ * 11) + BOOLEAN_SZ + - cannedKexAlgoNamesSz + cannedKeyAlgoNamesSz + - (cannedEncAlgoNamesSz * 2) + - (cannedMacAlgoNamesSz * 2) + - (cannedNoneNamesSz * 2); - ret = PreparePacket(ssh, payloadSz); - if (ret != WS_SUCCESS) - return ret; + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; - payload = output + idx; - - output[idx++] = MSGID_KEXINIT; - - ret = wc_RNG_GenerateBlock(ssh->rng, output + idx, COOKIE_SZ); - idx += COOKIE_SZ; - if (ret != 0) - return ret; - - CopyNameList(output, &idx, cannedKexAlgoNames, cannedKexAlgoNamesSz); - CopyNameList(output, &idx, cannedKeyAlgoNames, cannedKeyAlgoNamesSz); - CopyNameList(output, &idx, cannedEncAlgoNames, cannedEncAlgoNamesSz); - CopyNameList(output, &idx, cannedEncAlgoNames, cannedEncAlgoNamesSz); - CopyNameList(output, &idx, cannedMacAlgoNames, cannedMacAlgoNamesSz); - CopyNameList(output, &idx, cannedMacAlgoNames, cannedMacAlgoNamesSz); - CopyNameList(output, &idx, cannedNoneNames, cannedNoneNamesSz); - CopyNameList(output, &idx, cannedNoneNames, cannedNoneNamesSz); - c32toa(0, output + idx); /* Languages - Client To Server (0) */ - idx += LENGTH_SZ; - c32toa(0, output + idx); /* Languages - Server To Client (0) */ - idx += LENGTH_SZ; - output[idx++] = 0; /* First KEX packet follows (false) */ - c32toa(0, output + idx); /* Reserved (0) */ - idx += LENGTH_SZ; - - ssh->outputBuffer.length = idx; - - { - uint8_t scratchLen[LENGTH_SZ]; - c32toa(payloadSz, scratchLen); - ret = wc_ShaUpdate(&ssh->handshake->hash, scratchLen, LENGTH_SZ); - if (ret != 0) - return ret; + if (ret == WS_SUCCESS) { + payloadSz = MSG_ID_SZ + COOKIE_SZ + (LENGTH_SZ * 11) + BOOLEAN_SZ + + cannedKexAlgoNamesSz + cannedKeyAlgoNamesSz + + (cannedEncAlgoNamesSz * 2) + + (cannedMacAlgoNamesSz * 2) + + (cannedNoneNamesSz * 2); + ret = PreparePacket(ssh, payloadSz); } - ret = wc_ShaUpdate(&ssh->handshake->hash, payload, payloadSz); - if (ret != 0) - return ret; - ret = BundlePacket(ssh); + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; + payload = output + idx; + + output[idx++] = MSGID_KEXINIT; + + ret = wc_RNG_GenerateBlock(ssh->rng, output + idx, COOKIE_SZ); + } + + if (ret == WS_SUCCESS) { + idx += COOKIE_SZ; + + CopyNameList(output, &idx, cannedKexAlgoNames, cannedKexAlgoNamesSz); + CopyNameList(output, &idx, cannedKeyAlgoNames, cannedKeyAlgoNamesSz); + CopyNameList(output, &idx, cannedEncAlgoNames, cannedEncAlgoNamesSz); + CopyNameList(output, &idx, cannedEncAlgoNames, cannedEncAlgoNamesSz); + CopyNameList(output, &idx, cannedMacAlgoNames, cannedMacAlgoNamesSz); + CopyNameList(output, &idx, cannedMacAlgoNames, cannedMacAlgoNamesSz); + CopyNameList(output, &idx, cannedNoneNames, cannedNoneNamesSz); + CopyNameList(output, &idx, cannedNoneNames, cannedNoneNamesSz); + c32toa(0, output + idx); /* Languages - Client To Server (0) */ + idx += LENGTH_SZ; + c32toa(0, output + idx); /* Languages - Server To Client (0) */ + idx += LENGTH_SZ; + output[idx++] = 0; /* First KEX packet follows (false) */ + c32toa(0, output + idx); /* Reserved (0) */ + idx += LENGTH_SZ; + + ssh->outputBuffer.length = idx; + + c32toa(payloadSz, payloadSzFlat); + ret = wc_ShaUpdate(&ssh->handshake->hash, payloadSzFlat, LENGTH_SZ); + } + + if (ret == WS_SUCCESS) + ret = wc_ShaUpdate(&ssh->handshake->hash, payload, payloadSz); + + if (ret == WS_SUCCESS) + ret = BundlePacket(ssh); + if (ret == WS_SUCCESS) ret = SendBuffered(ssh); @@ -2723,50 +2872,54 @@ int SendNewKeys(WOLFSSH* ssh) { uint8_t* output; uint32_t idx = 0; - int ret; + int ret = WS_SUCCESS; - ret = PreparePacket(ssh, MSG_ID_SZ); - if (ret != WS_SUCCESS) - return ret; + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, MSG_ID_SZ); - output[idx++] = MSGID_NEWKEYS; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - ssh->outputBuffer.length = idx; + output[idx++] = MSGID_NEWKEYS; + + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); - if (ret != WS_SUCCESS) - return ret; + if (ret == WS_SUCCESS) { + ssh->blockSz = ssh->handshake->blockSz; + ssh->encryptId = ssh->handshake->encryptId; + ssh->macSz = ssh->handshake->macSz; + ssh->macId = ssh->handshake->macId; - ssh->blockSz = ssh->handshake->blockSz; - ssh->encryptId = ssh->handshake->encryptId; - ssh->macSz = ssh->handshake->macSz; - ssh->macId = ssh->handshake->macId; + switch (ssh->encryptId) { + case ID_NONE: + WLOG(WS_LOG_DEBUG, "SNK: using cipher none"); + break; - switch (ssh->encryptId) { - case ID_NONE: - WLOG(WS_LOG_DEBUG, "SNK: using cipher none"); - break; + case ID_AES128_CBC: + WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-cbc"); + ret = wc_AesSetKey(&ssh->encryptCipher.aes, + ssh->encKeyServer, ssh->encKeyServerSz, + ssh->ivServer, AES_ENCRYPTION); + break; - case ID_AES128_CBC: - WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-cbc"); - ret = wc_AesSetKey(&ssh->encryptCipher.aes, - ssh->encKeyServer, ssh->encKeyServerSz, - ssh->ivServer, AES_ENCRYPTION); - break; + default: + WLOG(WS_LOG_DEBUG, "SNK: using cipher invalid"); + ret = WS_INVALID_ALGO_ID; + } - default: - WLOG(WS_LOG_DEBUG, "SNK: using cipher invalid"); - break; + ssh->txCount = 0; } - ssh->txCount = 0; - return ret; } @@ -2775,22 +2928,27 @@ int SendUnimplemented(WOLFSSH* ssh) { uint8_t* output; uint32_t idx = 0; - int ret; + int ret = WS_SUCCESS; - ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ); - if (ret != WS_SUCCESS) - return ret; + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ); - output[idx++] = MSGID_UNIMPLEMENTED; - c32toa(ssh->peerSeq, output + idx); - idx += UINT32_SZ; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - ssh->outputBuffer.length = idx; + output[idx++] = MSGID_UNIMPLEMENTED; + c32toa(ssh->peerSeq, output + idx); + idx += UINT32_SZ; + + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); @@ -2802,26 +2960,31 @@ int SendDisconnect(WOLFSSH* ssh, uint32_t reason) { uint8_t* output; uint32_t idx = 0; - int ret; + int ret = WS_SUCCESS; - ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + (LENGTH_SZ * 2)); - if (ret != WS_SUCCESS) - return ret; + if (ssh == NULL) + ret = WS_BAD_ARGUMENT; - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + (LENGTH_SZ * 2)); - output[idx++] = MSGID_DISCONNECT; - c32toa(reason, output + idx); - idx += UINT32_SZ; - c32toa(0, output + idx); - idx += LENGTH_SZ; - c32toa(0, output + idx); - idx += LENGTH_SZ; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - ssh->outputBuffer.length = idx; + output[idx++] = MSGID_DISCONNECT; + c32toa(reason, output + idx); + idx += UINT32_SZ; + c32toa(0, output + idx); + idx += LENGTH_SZ; + c32toa(0, output + idx); + idx += LENGTH_SZ; + + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); @@ -2833,29 +2996,31 @@ int SendIgnore(WOLFSSH* ssh, const unsigned char* data, uint32_t dataSz) { uint8_t* output; uint32_t idx = 0; - int ret; + int ret = WS_SUCCESS; if (ssh == NULL || (data == NULL && dataSz > 0)) - return WS_BAD_ARGUMENT; + ret = WS_BAD_ARGUMENT; - ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + dataSz); - if (ret != WS_SUCCESS) - return ret; + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + dataSz); - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - output[idx++] = MSGID_IGNORE; - c32toa(dataSz, output + idx); - idx += LENGTH_SZ; - if (dataSz > 0) { - WMEMCPY(output + idx, data, dataSz); - idx += dataSz; + output[idx++] = MSGID_IGNORE; + c32toa(dataSz, output + idx); + idx += LENGTH_SZ; + if (dataSz > 0) { + WMEMCPY(output + idx, data, dataSz); + idx += dataSz; + } + + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); } - ssh->outputBuffer.length = idx; - - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); @@ -2872,38 +3037,41 @@ int SendDebug(WOLFSSH* ssh, byte alwaysDisplay, const char* msg) uint32_t msgSz; uint8_t* output; uint32_t idx = 0; - int ret; + int ret = WS_SUCCESS; if (ssh == NULL) - return WS_BAD_ARGUMENT; + ret = WS_BAD_ARGUMENT; - msgSz = (msg != NULL) ? (uint32_t)WSTRLEN(msg) : 0; + if (ret == WS_SUCCESS) { + msgSz = (msg != NULL) ? (uint32_t)WSTRLEN(msg) : 0; - ret = PreparePacket(ssh, - MSG_ID_SZ + BOOLEAN_SZ + (LENGTH_SZ * 2) + - msgSz + cannedLangTagSz); - if (ret != WS_SUCCESS) - return ret; - - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; - - output[idx++] = MSGID_DEBUG; - output[idx++] = (alwaysDisplay != 0); - c32toa(msgSz, output + idx); - idx += LENGTH_SZ; - if (msgSz > 0) { - WMEMCPY(output + idx, msg, msgSz); - idx += msgSz; + ret = PreparePacket(ssh, + MSG_ID_SZ + BOOLEAN_SZ + (LENGTH_SZ * 2) + + msgSz + cannedLangTagSz); } - c32toa(cannedLangTagSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, cannedLangTag, cannedLangTagSz); - idx += cannedLangTagSz; - ssh->outputBuffer.length = idx; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; + + output[idx++] = MSGID_DEBUG; + output[idx++] = (alwaysDisplay != 0); + c32toa(msgSz, output + idx); + idx += LENGTH_SZ; + if (msgSz > 0) { + WMEMCPY(output + idx, msg, msgSz); + idx += msgSz; + } + c32toa(cannedLangTagSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, cannedLangTag, cannedLangTagSz); + idx += cannedLangTagSz; + + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); @@ -2919,28 +3087,31 @@ int SendServiceAccept(WOLFSSH* ssh) uint32_t nameSz; uint8_t* output; uint32_t idx; - int ret; + int ret = WS_SUCCESS; if (ssh == NULL) - return WS_BAD_ARGUMENT; + ret = WS_BAD_ARGUMENT; - nameSz = (uint32_t)WSTRLEN(userAuthName); - ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + nameSz); - if (ret != WS_SUCCESS) - return ret; + if (ret == WS_SUCCESS) { + nameSz = (uint32_t)WSTRLEN(userAuthName); + ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + nameSz); + } - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - output[idx++] = MSGID_SERVICE_ACCEPT; - c32toa(nameSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, userAuthName, nameSz); - idx += nameSz; + output[idx++] = MSGID_SERVICE_ACCEPT; + c32toa(nameSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, userAuthName, nameSz); + idx += nameSz; - ssh->outputBuffer.length = idx; + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendUserAuthBanner(ssh); @@ -2956,33 +3127,34 @@ int SendUserAuthFailure(WOLFSSH* ssh, uint8_t partialSuccess) { uint8_t* output; uint32_t idx; - int ret; - - (void)partialSuccess; + int ret = WS_SUCCESS; WLOG(WS_LOG_DEBUG, "Entering SendUserAuthFailure()"); if (ssh == NULL) - return WS_BAD_ARGUMENT; + ret = WS_BAD_ARGUMENT; - ret = PreparePacket(ssh, - MSG_ID_SZ + LENGTH_SZ + cannedAuthsSz + BOOLEAN_SZ); - if (ret != WS_SUCCESS) - return ret; + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, + MSG_ID_SZ + LENGTH_SZ + + cannedAuthsSz + BOOLEAN_SZ); - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - output[idx++] = MSGID_USERAUTH_FAILURE; - c32toa(cannedAuthsSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, cannedAuths, cannedAuthsSz); - idx += cannedAuthsSz; - output[idx++] = 0; + output[idx++] = MSGID_USERAUTH_FAILURE; + c32toa(cannedAuthsSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, cannedAuths, cannedAuthsSz); + idx += cannedAuthsSz; + output[idx++] = (partialSuccess != 0); - ssh->outputBuffer.length = idx; + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); @@ -2994,23 +3166,25 @@ int SendUserAuthSuccess(WOLFSSH* ssh) { uint8_t* output; uint32_t idx; - int ret; + int ret = WS_SUCCESS; if (ssh == NULL) - return WS_BAD_ARGUMENT; + ret = WS_BAD_ARGUMENT; - ret = PreparePacket(ssh, MSG_ID_SZ); - if (ret != WS_SUCCESS) - return ret; + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, MSG_ID_SZ); - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - output[idx++] = MSGID_USERAUTH_SUCCESS; + output[idx++] = MSGID_USERAUTH_SUCCESS; - ssh->outputBuffer.length = idx; + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); @@ -3024,34 +3198,40 @@ int SendUserAuthPkOk(WOLFSSH* ssh, { uint8_t* output; uint32_t idx; - int ret; + int ret = WS_SUCCESS; if (ssh == NULL || algoName == NULL || algoNameSz == 0 || publicKey == NULL || publicKeySz == 0) { - return WS_BAD_ARGUMENT; + ret = WS_BAD_ARGUMENT; } - PreparePacket(ssh, MSG_ID_SZ + (LENGTH_SZ * 2) + algoNameSz + publicKeySz); + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, MSG_ID_SZ + (LENGTH_SZ * 2) + + algoNameSz + publicKeySz); - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - output[idx++] = MSGID_USERAUTH_PK_OK; - c32toa(algoNameSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, algoName, algoNameSz); - idx += algoNameSz; - c32toa(publicKeySz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, publicKey, publicKeySz); - idx += publicKeySz; + output[idx++] = MSGID_USERAUTH_PK_OK; + c32toa(algoNameSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, algoName, algoNameSz); + idx += algoNameSz; + c32toa(publicKeySz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, publicKey, publicKeySz); + idx += publicKeySz; - ssh->outputBuffer.length = idx; + ssh->outputBuffer.length = idx; - BundlePacket(ssh); - ret = SendBuffered(ssh); + ret = BundlePacket(ssh); + } + + if (ret == WS_SUCCESS) + ret = SendBuffered(ssh); return ret; } @@ -3070,32 +3250,34 @@ int SendUserAuthBanner(WOLFSSH* ssh) { uint8_t* output; uint32_t idx; - int ret; + int ret = WS_SUCCESS; if (ssh == NULL) - return WS_BAD_ARGUMENT; + ret = WS_BAD_ARGUMENT; - ret = PreparePacket(ssh, MSG_ID_SZ + (LENGTH_SZ * 2) + - cannedBannerSz + cannedLangTagSz); - if (ret != WS_SUCCESS) - return ret; + if (ret == WS_SUCCESS) + ret = PreparePacket(ssh, MSG_ID_SZ + (LENGTH_SZ * 2) + + cannedBannerSz + cannedLangTagSz); - output = ssh->outputBuffer.buffer; - idx = ssh->outputBuffer.length; + if (ret == WS_SUCCESS) { + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; - output[idx++] = MSGID_USERAUTH_BANNER; - c32toa(cannedBannerSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, cannedBanner, cannedBannerSz); - idx += cannedBannerSz; - c32toa(cannedLangTagSz, output + idx); - idx += LENGTH_SZ; - WMEMCPY(output + idx, cannedLangTag, cannedLangTagSz); - idx += cannedLangTagSz; + output[idx++] = MSGID_USERAUTH_BANNER; + c32toa(cannedBannerSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, cannedBanner, cannedBannerSz); + idx += cannedBannerSz; + c32toa(cannedLangTagSz, output + idx); + idx += LENGTH_SZ; + WMEMCPY(output + idx, cannedLangTag, cannedLangTagSz); + idx += cannedLangTagSz; - ssh->outputBuffer.length = idx; + ssh->outputBuffer.length = idx; + + ret = BundlePacket(ssh); + } - ret = BundlePacket(ssh); if (ret == WS_SUCCESS) ret = SendBuffered(ssh); diff --git a/wolfssh/error.h b/wolfssh/error.h index b94ab2bf..49a51e40 100644 --- a/wolfssh/error.h +++ b/wolfssh/error.h @@ -67,7 +67,8 @@ enum WS_ErrorCodes { WS_RESOURCE_E = -25, /* insufficient resources for new channel */ WS_INVALID_CHANTYPE = -26, /* invalid channel type */ WS_INVALID_CHANID = -27, - WS_INVALID_USERNAME = -28 + WS_INVALID_USERNAME = -28, + WS_CRYPTO_FAILED = -29 /* crypto action failed */ };