-
Notifications
You must be signed in to change notification settings - Fork 121
Follow up for PR 1218 #1239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Follow up for PR 1218 #1239
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1337,6 +1337,7 @@ WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap) | |
| ctx->maxPacketSz = DEFAULT_MAX_PACKET_SZ; | ||
| ctx->maxAuthAttempts = DEFAULT_MAX_AUTH_ATTEMPTS; | ||
| ctx->sshProtoIdStr = sshProtoIdStr; | ||
| ctx->sshProtoIdStrSz = (word32)(sizeof(sshProtoIdStr) - 1); | ||
| ctx->algoListKex = cannedKexAlgoNames; | ||
| if (side == WOLFSSH_ENDPOINT_CLIENT) { | ||
| ctx->algoListKey = cannedKeyAlgoNamesHostKey; | ||
|
|
@@ -6533,9 +6534,8 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) | |
| } | ||
|
|
||
| if (ret == WS_SUCCESS) { | ||
| byte SSH_PROTO_EOL_SZ = 2; | ||
|
|
||
| strSz = (word32)WSTRLEN(ssh->ctx->sshProtoIdStr) - SSH_PROTO_EOL_SZ; | ||
| /* The ID is hashed without its terminator. */ | ||
| strSz = ssh->ctx->sshProtoIdStrSz - SSH_PROTO_EOL_SZ; | ||
| c32toa(strSz, scratchLen); | ||
| ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); | ||
| } | ||
|
|
@@ -14185,21 +14185,50 @@ int DoProtoId(WOLFSSH* ssh) | |
| /* Validates a locally configured proto ID string */ | ||
| int ValidateProtoId(const char* protoIdStr, word32 len) | ||
| { | ||
| /* Length is checked first: the prefix, terminator, and body checks below | ||
| * index and subtract from len. The minimum is the "SSH-2.0-" prefix plus | ||
| * one body byte plus CRLF. */ | ||
| if (protoIdStr == NULL || len < SSH_PROTO_SZ + 3 || | ||
| protoIdStr[len-1] != '\n' || protoIdStr[len-2] != '\r' || | ||
| len > WOLFSSH_PROTOID_LIMIT || | ||
| WSTRNCMP(protoIdStr, sshProtoIdPrefix, SSH_PROTO_SZ) != 0 || | ||
| WSTRNSTR(protoIdStr, "\n", len - 2) != NULL || | ||
| WSTRNSTR(protoIdStr, "\r", len - 2) != NULL) { | ||
| word32 i; | ||
|
|
||
| /* The length check must stay first: every check below indexes into | ||
| * protoIdStr or subtracts from the unsigned len. The minimum is the | ||
| * "SSH-2.0-" prefix plus one body byte plus CRLF. */ | ||
| if (protoIdStr == NULL || | ||
| len < SSH_PROTO_MIN || | ||
| len > WOLFSSH_PROTOID_LIMIT) { | ||
| WLOG(WS_LOG_ERROR, "Proto Id was invalid: it must be between %d and " | ||
| "%d bytes, counting the prefix and the terminator", | ||
| SSH_PROTO_MIN, WOLFSSH_PROTOID_LIMIT); | ||
| return WS_BAD_ARGUMENT; | ||
| } | ||
|
|
||
| if (WSTRNCMP(protoIdStr, sshProtoIdPrefix, SSH_PROTO_SZ) != 0) { | ||
| WLOG(WS_LOG_ERROR, "Proto Id was invalid: it must start with " | ||
| "\"SSH-2.0-\", end in \\r\\n, be no longer than %d bytes, " | ||
| "and must not contain \\r or \\n in the body of the line", | ||
| WOLFSSH_PROTOID_LIMIT); | ||
| "\"SSH-2.0-\""); | ||
| return WS_BAD_ARGUMENT; | ||
| } | ||
|
|
||
| /* RFC 4253 section 4.2 splits the line as "SSH-2.0-" softwareversion | ||
| * [SP comments] CRLF. A leading space would make softwareversion | ||
| * empty, so reject it. */ | ||
| if (protoIdStr[SSH_PROTO_SZ] == ' ') { | ||
| WLOG(WS_LOG_ERROR, "Proto Id was invalid: the body must start with a " | ||
| "non-space character"); | ||
| return WS_BAD_ARGUMENT; | ||
| } | ||
|
|
||
| if (protoIdStr[len - 1] != '\n' || protoIdStr[len - 2] != '\r') { | ||
| WLOG(WS_LOG_ERROR, "Proto Id was invalid: it must end in \\r\\n"); | ||
| return WS_BAD_ARGUMENT; | ||
| } | ||
|
|
||
| for (i = 0; i < len - SSH_PROTO_EOL_SZ; i++) { | ||
| byte c = (byte)protoIdStr[i]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the record, no change needed. RFC 4253 Section 4.2 has If anything, a one-line comment noting that SP is permitted on purpose (it separates the RFC 4253
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added comment |
||
| /* spaces are intetionally allowed */ | ||
| if (c < 0x20 || c > 0x7e) { | ||
| WLOG(WS_LOG_ERROR, "Proto Id was invalid: byte %u is " | ||
| "not printable US-ASCII", i); | ||
| return WS_BAD_ARGUMENT; | ||
| } | ||
| } | ||
|
|
||
| return WS_SUCCESS; | ||
| } | ||
|
|
||
|
|
@@ -14214,7 +14243,7 @@ int SendProtoId(WOLFSSH* ssh) | |
|
|
||
| if (ret == WS_SUCCESS) { | ||
| WLOG(WS_LOG_DEBUG, "%s", ssh->ctx->sshProtoIdStr); | ||
| sshProtoIdStrSz = (word32)WSTRLEN(ssh->ctx->sshProtoIdStr); | ||
| sshProtoIdStrSz = ssh->ctx->sshProtoIdStrSz; | ||
| ret = GrowBuffer(&ssh->outputBuffer, sshProtoIdStrSz); | ||
| } | ||
|
|
||
|
|
@@ -24251,6 +24280,11 @@ int wolfSSH_TestDoProtoId(WOLFSSH* ssh) | |
| return DoProtoId(ssh); | ||
| } | ||
|
|
||
| int wolfSSH_TestSendProtoId(WOLFSSH* ssh) | ||
| { | ||
| return SendProtoId(ssh); | ||
| } | ||
|
|
||
| int wolfSSH_TestIsMessageAllowed(WOLFSSH* ssh, byte msg, byte state) | ||
| { | ||
| return IsMessageAllowed(ssh, msg, state); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing in the tree drives a handshake with a custom proto ID.
wolfSSH_CTX_SetSshProtoIdStr()has exactly one caller, the unit test, and that only checks the accept/reject verdict and the stored size. So the one path this field exists for has no KEX coverage, and a desync betweensshProtoIdStrandsshProtoIdStrSzwould surface only as an exchange-hash mismatch, which is a miserable failure to diagnose.No live defect --
CtxInit()and the setter both assign the string and the size from the same source in the same breath -- so this is optional rather than owed. If it does get written, the max-length case is the interesting one, and it should pass: a 255-byte ID is 253 body bytes plus CRLF, and the peer'sGetInputLine()reads all 255 in one go and finds the LF before thelength >= WOLFSSH_PROTOID_LIMITcap fires. The accept boundary this PR adds does round-trip.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created round trip test!