diff --git a/3rdp/build/cl-server-term-support.patch b/3rdp/build/cl-server-term-support.patch index 55cd92bc53e53bd0aa0358a41f277122b78e930d..4d4e62cfc4b6b686b9561b4e3f65eb8c1585eaa0 100644 --- a/3rdp/build/cl-server-term-support.patch +++ b/3rdp/build/cl-server-term-support.patch @@ -32,34 +32,40 @@ default: retIntError(); } -@@ -479,6 +497,14 @@ +@@ -479,6 +497,18 @@ case CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE: *value = isActiveChannel( channelInfoPtr ) ? TRUE : FALSE; return( CRYPT_OK ); + + case CRYPT_SESSINFO_SSH_CHANNEL_WIDTH: ++ if (channelInfoPtr->width == 0) ++ return CRYPT_ERROR_NOTFOUND; + *value = channelInfoPtr->width; + return( CRYPT_OK ); + + case CRYPT_SESSINFO_SSH_CHANNEL_HEIGHT: ++ if (channelInfoPtr->height == 0) ++ return CRYPT_ERROR_NOTFOUND; + *value = channelInfoPtr->height; + return( CRYPT_OK ); } retIntError(); -@@ -532,6 +558,11 @@ +@@ -532,6 +562,13 @@ return( attributeCopyParams( data, dataMaxLength, dataLength, channelInfoPtr->arg2, channelInfoPtr->arg2Len ) ); + + case CRYPT_SESSINFO_SSH_CHANNEL_TERMINAL: ++ if (channelInfoPtr->terminalLen == 0) ++ return CRYPT_ERROR_NOTFOUND; + return( attributeCopyParams( data, dataMaxLength, dataLength, + channelInfoPtr->terminal, + channelInfoPtr->terminalLen ) ); } retIntError(); -@@ -596,7 +627,21 @@ +@@ -596,7 +633,21 @@ return( selectChannel( sessionInfoPtr, channelInfoPtr->writeChannelNo, CHANNEL_WRITE ) ); } @@ -81,7 +87,7 @@ retIntError(); } -@@ -639,6 +684,11 @@ +@@ -639,6 +688,11 @@ return( attributeCopyParams( channelInfoPtr->arg2, CRYPT_MAX_TEXTSIZE, &channelInfoPtr->arg2Len, diff --git a/src/sftp/sftp.h b/src/sftp/sftp.h index 2d12851cded3225da2b6c88443cc807c583582d1..2eec8caae361e2abc1ed0fe8992ba7c81330c6b1 100644 --- a/src/sftp/sftp.h +++ b/src/sftp/sftp.h @@ -58,7 +58,7 @@ #define SSH_FILEXFER_ATTR_PERMISSIONS UINT32_C(0x00000004) #define SSH_FILEXFER_ATTR_ACMODTIME UINT32_C(0x00000008) #define SSH_FILEXFER_ATTR_EXTENDED UINT32_C(0x80000000) - + #define SFTP_MIN_PACKET_ALLOC 4096 #define SFTP_VERSION 3 diff --git a/src/sftp/sftp_client.c b/src/sftp/sftp_client.c index 012db6e674351231b77cff51b5dd836a0f195f28..8fb6b8ce6d3fdbd5b48614f75b6dd05ebe5b7dc4 100644 --- a/src/sftp/sftp_client.c +++ b/src/sftp/sftp_client.c @@ -188,7 +188,6 @@ static void handle_error(sftpc_state_t state) { if (state->rxp->type == SSH_FXP_STATUS) { - state->err_id = get32(state); state->err_code = get32(state); if (state->err_msg != NULL) free_sftp_str(state->err_msg); @@ -358,6 +357,7 @@ sftpc_read(sftpc_state_t state, sftp_filehandle_t handle, uint64_t offset, uint3 return false; if (state->rxp->type == SSH_FXP_DATA) { *ret = getstring(state); + response_handled(state); return *ret != NULL; } handle_error(state); diff --git a/src/sftp/sftp_pkt.c b/src/sftp/sftp_pkt.c index 4c2cc82db726392d24debd235bb6214f2c1a047b..c567740efcd2625bd10ee4ea3d49066cce757c60 100644 --- a/src/sftp/sftp_pkt.c +++ b/src/sftp/sftp_pkt.c @@ -154,7 +154,7 @@ sftp_get64(sftp_rx_pkt_t pkt) { uint64_t ret; GET_FUNC_BODY; - return BE_INT32(ret); + return BE_INT64(ret); } /* diff --git a/src/sftp/sftp_str.c b/src/sftp/sftp_str.c index 10aa3fa103ad395c74998f3f3bf783c4cf45ee5e..7f743a5eae8a38b31624a41824de2befcd0ebba6 100644 --- a/src/sftp/sftp_str.c +++ b/src/sftp/sftp_str.c @@ -36,7 +36,7 @@ sftp_asprintf(const char *format, ...) va_list va; va_start(va, format); - char *str = xp_asprintf(format, va); + char *str = xp_vasprintf(format, va); va_end(va); if (str == NULL) return NULL; diff --git a/src/syncterm/ssh.c b/src/syncterm/ssh.c index d389c564ec89a33865b89fde4e712fd45b2f2785..df7be2d4fee851f86e7c4285a147d6b1a4be2c6e 100644 --- a/src/syncterm/ssh.c +++ b/src/syncterm/ssh.c @@ -256,15 +256,14 @@ get_public_key(CRYPT_CONTEXT ctx) status = cl.GetAttributeString(ctx, CRYPT_CTXINFO_SSH_PUBLIC_KEY, NULL, &sz); if (cryptStatusOK(status)) { - fprintf(stderr, "Size: %d\n", sz); raw = malloc(sz); if (raw != NULL) { status = cl.GetAttributeString(ctx, CRYPT_CTXINFO_SSH_PUBLIC_KEY, raw, &sz); if (cryptStatusOK(status)) { - rsz = sz * 4 / 3 + 3; + rsz = (sz - 4) * 4 / 3 + 3; ret = malloc(rsz); if (ret != NULL) { - b64_encode(ret, rsz, raw, sz); + b64_encode(ret, rsz, raw + 4, sz - 4); free(raw); return ret; } @@ -272,10 +271,75 @@ get_public_key(CRYPT_CONTEXT ctx) free(raw); } } - fprintf(stderr, "Error %d\n", status); return NULL; } +static bool +key_not_present(sftp_filehandle_t f, const char *priv) +{ + size_t bufsz = 0; + size_t old_bufpos = 0; + size_t bufpos = 0; + size_t off = 0; + size_t eol; + char *buf = NULL; + char *newbuf; + char *eolptr; + sftp_str_t r = NULL; + bool skipread = false; + + do { + if (skipread) { + old_bufpos = 0; + skipread = false; + } + else { + if (bufsz - bufpos < 1024) { + newbuf = realloc(buf, bufsz + 4096); + if (newbuf == NULL) { + free(buf); + return false; + } + buf = newbuf; + bufsz += 4096; + } + if (!sftpc_read(sftp_state, f, off, (bufsz - bufpos > 1024) ? 1024 : bufsz - bufpos, &r)) { + if (sftp_state->err_code == SSH_FX_EOF) { + free(buf); + free_sftp_str(r); + return true; + } + free(buf); + return false; + } + memcpy(&buf[bufpos], r->c_str, r->len); + old_bufpos = bufpos; + bufpos += r->len; + off += r->len; + free_sftp_str(r); + r = NULL; + } + for (eol = old_bufpos; eol < bufpos; eol++) { + if (buf[eol] == '\r' || buf[eol] == '\n') + break; + } + if (eol < bufpos) { + skipread = true; + eolptr = &buf[eol]; + *eolptr = 0; + if (strstr(buf, priv) != NULL) { + free(buf); + return false; + } + *eolptr = '\n'; + while (eol < bufpos && (buf[eol] == '\r' || buf[eol] == '\n')) + eol++; + memmove(buf, &buf[eol], bufpos - eol); + bufpos = bufpos - eol; + } + } while(1); +} + static bool add_public_key(struct bbslist *bbs, char *priv) { @@ -325,14 +389,17 @@ add_public_key(struct bbslist *bbs, char *priv) sftp_state = sftpc_begin(sftp_send, NULL); if (sftp_state != NULL) { if (sftpc_init(sftp_state)) { - sftp_str_t ret = NULL; sftp_filehandle_t f = NULL; - - if (sftpc_open(sftp_state, ".ssh/authorized_keys", SSH_FXF_READ, NULL, &f)) { - if (sftpc_read(sftp_state, f, 0, 1024, &ret)) { - fprintf(stderr, "First lines... %s\n", ret->c_str); - free_sftp_str(ret); - added = true; + // TODO: Add permissions? + + if (sftpc_open(sftp_state, ".ssh/authorized_keys", SSH_FXF_READ | SSH_FXF_WRITE | SSH_FXF_APPEND | SSH_FXF_CREAT, NULL, &f)) { + /* Read through the file looking for our key */ + if (key_not_present(f, priv)) { + // TODO: Types other than RSA... + sftp_str_t ln = sftp_asprintf("ssh-rsa %s Added by SyncTERM\n", priv); + if (ln != NULL) { + sftpc_write(sftp_state, f, 0, ln); + } } sftpc_close(sftp_state, &f); } @@ -479,7 +546,7 @@ ssh_connect(struct bbslist *bbs) return -1; } - /* we need to disable Nagle on the socket. */ + /* we need to disable Nagle on the socket. */ if (setsockopt(ssh_sock, IPPROTO_TCP, TCP_NODELAY, (char *)&off, sizeof(off))) fprintf(stderr, "%s:%d: Error %d calling setsockopt()\n", __FILE__, __LINE__, errno); @@ -500,7 +567,7 @@ ssh_connect(struct bbslist *bbs) if (!bbs->hidepopups) uifc.pop("Setting Username"); - /* Add username/password */ + /* Add username/password */ status = cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_USERNAME, username, strlen(username)); if (cryptStatusError(status)) { error_popup(bbs, "setting username", status); @@ -517,7 +584,7 @@ ssh_connect(struct bbslist *bbs) } } else { - if (!password[0]) { + if (!password[0]/* && ssh_context == -1*/) { if (bbs->hidepopups) init_uifc(false, false); uifcinput("Password", MAX_PASSWD_LEN, password, K_PASSWORD, "Incorrect password. Try again."); @@ -525,12 +592,14 @@ ssh_connect(struct bbslist *bbs) uifcbail(); } - if (!bbs->hidepopups) - uifc.pop("Setting Password"); - status = cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, password, strlen(password)); - if (cryptStatusError(status)) { - error_popup(bbs, "setting password", status); - return -1; + if (password[0]) { + if (!bbs->hidepopups) + uifc.pop("Setting Password"); + status = cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, password, strlen(password)); + if (cryptStatusError(status)) { + error_popup(bbs, "setting password", status); + return -1; + } } if (ssh_context != -1) { @@ -539,6 +608,7 @@ ssh_connect(struct bbslist *bbs) pubkey = get_public_key(ssh_context); status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_PRIVATEKEY, ssh_context); cl.DestroyContext(ssh_context); + ssh_context = -1; if (cryptStatusError(status)) { free(pubkey); error_popup(bbs, "setting private key", status); @@ -552,7 +622,7 @@ ssh_connect(struct bbslist *bbs) uifc.pop("Setting Username"); } - /* Pass socket to cryptlib */ + /* Pass socket to cryptlib */ status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_NETWORKSOCKET, ssh_sock); if (cryptStatusError(status)) { free(pubkey); @@ -560,6 +630,9 @@ ssh_connect(struct bbslist *bbs) return -1; } + // We need to set the channel so we can set channel attributes. + status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, CRYPT_UNUSED); + if (!bbs->hidepopups) { uifc.pop(NULL); uifc.pop("Setting Terminal Type"); @@ -583,7 +656,7 @@ ssh_connect(struct bbslist *bbs) cl.SetAttribute(ssh_session, CRYPT_OPTION_NET_READTIMEOUT, 1); - /* Activate the session */ + /* Activate the session */ if (!bbs->hidepopups) { uifc.pop(NULL); uifc.pop("Activating Session"); @@ -674,8 +747,6 @@ ssh_connect(struct bbslist *bbs) } } bbs->has_fingerprint = true; - } else { - fprintf(stderr, "Failed to get fingerprint. :(\n"); } if (!bbs->hidepopups)