├── auth.c ├── bin ├── scp2d386.exe ├── scp2dos.exe ├── sftpd386.exe ├── sftpdos.exe ├── ssh2d386.exe ├── ssh2dos.exe ├── tel386.exe └── telnet.exe ├── channel.c ├── common.c ├── contrib ├── frontend │ ├── copying │ ├── frontend.txt │ ├── getopt.c │ ├── getopt.h │ ├── makef386 │ ├── makefile │ ├── regex.c │ ├── regex.h │ ├── ssh.c │ ├── ssh1.cfg │ └── ssh2.cfg └── keycodes │ ├── copying │ └── keycodes.asm ├── copying ├── docs ├── bugs ├── drafts │ ├── architec.txt │ ├── connect.txt │ ├── filexfer.txt │ ├── kbdinter.txt │ ├── transprt.txt │ └── userauth.txt ├── history ├── readme └── todo ├── include ├── auth.h ├── channel.h ├── common.h ├── config.h ├── int64.h ├── keyio.h ├── keymap.h ├── macros.h ├── negotiat.h ├── proxy.h ├── pubkey.h ├── sftp.h ├── shell.h ├── ssh.h ├── sshbn.h ├── sshmd5.h ├── sshsha.h ├── telnet.h ├── transprt.h ├── type.h ├── version.h ├── vidio.h ├── vttio.h ├── zconf.h └── zlib.h ├── int64.c ├── keyio.c ├── keymap.c ├── linux.kbd ├── negotiat.c ├── proxy.c ├── scp2d386.lnk ├── scp2dos.lnk ├── scpdos.c ├── sftp.c ├── sftpd386.lnk ├── sftpdos.c ├── sftpdos.lnk ├── shell.c ├── ssh2d386.lnk ├── ssh2dos.c ├── ssh2dos.lnk ├── sshaes.c ├── sshbn.c ├── sshdes.c ├── sshdss.c ├── sshmd5.c ├── sshpubk.c ├── sshrsa.c ├── sshsh256.c ├── sshsh512.c ├── sshsha.c ├── tel386.lnk ├── telnet.c ├── telnet.lnk ├── transprt.c ├── vidio.c ├── vt100.kbd ├── vt340.kbd ├── vttio.c ├── watcom_f.mak ├── watcom_l.mak ├── wattcp.cfg └── x-color.kbd /auth.c: -------------------------------------------------------------------------------- 1 | /* auth.c Copyright (c) 2000-2005 Nagy Daniel 2 | * 3 | * $Date: 2005/12/30 16:26:40 $ 4 | * $Revision: 1.4 $ 5 | * 6 | * This module is the authentication layer. 7 | * 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 2 12 | * of the License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Library General Public 20 | * License along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "auth.h" 30 | #include "config.h" 31 | #include "macros.h" 32 | #include "pubkey.h" 33 | #include "ssh.h" 34 | #include "transprt.h" 35 | #include "common.h" 36 | #if defined (MEMWATCH) 37 | #include "memwatch.h" 38 | #endif 39 | 40 | /* external functions, data */ 41 | extern Packet pktin; /* incoming SSH2 packet */ 42 | extern Packet pktout; /* outgoing SSH2 packet */ 43 | extern unsigned char ssh2_session_id[32]; /* session ID */ 44 | extern Config GlobalConfig; /* configuration variables */ 45 | extern unsigned short Configuration; /* configuration bitfields */ 46 | extern struct ssh2_userkey ssh2_wrong_passphrase; 47 | extern char *protocolerror; 48 | 49 | /* 50 | * Allocate memory for password and ask for password. 51 | * Don't forget to free it later. 52 | */ 53 | static char *AskPassword(void) 54 | { 55 | char *password; 56 | unsigned short len = 0; 57 | unsigned char ch; 58 | 59 | // flush kb input 60 | while(kbhit()){ 61 | getch(); 62 | } 63 | 64 | if((password = (char *)malloc(MAX_PASSWORD_LENGTH * sizeof(char))) == NULL) 65 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 66 | while((ch = getch()) != 0x0d && len < MAX_PASSWORD_LENGTH){ 67 | if(ch == 8 && len > 0) 68 | password[--len] = 0; 69 | else if(ch >= 32) 70 | password[len++] = ch; 71 | } /* while */ 72 | password[len] = '\0'; 73 | cputs("\r\n"); 74 | return(password); 75 | } 76 | 77 | 78 | /* 79 | * Send ignore packet to make protocol analisys harder 80 | */ 81 | static void SendIgnores(void) 82 | { 83 | unsigned char randbuf[100]; 84 | unsigned short j, k; 85 | 86 | j = 10 + rand() % (sizeof(randbuf) - 10); 87 | for(k = 0; k < j; k++) 88 | randbuf[k] = rand() % 256; /* fill random buffer */ 89 | 90 | SSH_pkt_init(SSH_MSG_IGNORE); 91 | SSH_putdata(randbuf, j); 92 | SSH_pkt_send(); 93 | } 94 | 95 | /* 96 | * Try public key authentication 97 | */ 98 | short SSH2_Auth_Pubkey(char *username, char *keyfile) 99 | { 100 | int type, i; 101 | char *password = NULL, *comment; 102 | unsigned char *pkblob, *sigblob, *sigdata; 103 | int pkblob_len, sigblob_len, sigdata_len; 104 | struct ssh2_userkey *key; 105 | 106 | if(keyfile == NULL) /* is there a key file? */ 107 | return(1); /* go and try password authentication */ 108 | 109 | if(Configuration & VERBOSE_MODE) 110 | puts("Begin public key authentication"); 111 | 112 | /* Check key */ 113 | type = key_type(keyfile); 114 | if(type != SSH_KEYTYPE_SSH2 && type != SSH_KEYTYPE_OPENSSH){ 115 | if(Configuration & VERBOSE_MODE) 116 | printf("Key is of wrong type (%s)\r\n", key_type_to_str(type)); 117 | return(1); /* go and try password authentication */ 118 | } 119 | 120 | /* Check if encrypted */ 121 | if(type == SSH_KEYTYPE_SSH2) 122 | i = ssh2_userkey_encrypted(keyfile, &comment); 123 | else{ 124 | /* OpenSSH doesn't do key comments */ 125 | comment = strdup(keyfile); 126 | i = openssh_encrypted(keyfile); 127 | } 128 | 129 | /* Get passphrase if encrypted */ 130 | if(i){ 131 | cprintf("Passphrase for key \"%.100s\": ", comment); 132 | password = AskPassword(); 133 | } /* if */ 134 | else 135 | if(Configuration & VERBOSE_MODE) 136 | puts("No passphrase required"); 137 | free(comment); 138 | 139 | /* Try to load key */ 140 | if(type == SSH_KEYTYPE_SSH2) 141 | key = ssh2_load_userkey(keyfile, password); 142 | else 143 | key = openssh_read(keyfile, password); 144 | 145 | if(password) 146 | free(password); 147 | 148 | if(key == SSH2_WRONG_PASSPHRASE){ 149 | puts("Wrong passphrase"); 150 | return(1); /* go and try password authentication */ 151 | } 152 | 153 | /* 154 | * First, offer the public blob to see if the server is 155 | * willing to accept it. 156 | */ 157 | pkblob = key->alg->public_blob(key->data, &pkblob_len); 158 | 159 | SSH2_Auth_PktInit(SSH_MSG_USERAUTH_REQUEST, username); 160 | SSH_putstring("publickey"); 161 | SSH_putbool(0); 162 | SSH_putstring(key->alg->name); 163 | SSH_putuint32(pkblob_len); 164 | SSH_putdata(pkblob, pkblob_len); 165 | SSH_pkt_send(); 166 | 167 | if(SSH2_Auth_Read(0)) 168 | return(1); 169 | 170 | switch(pktin.type){ 171 | case SSH_MSG_USERAUTH_PK_OK: 172 | break; 173 | 174 | case SSH_MSG_USERAUTH_FAILURE: 175 | puts("Host refused our key"); 176 | return(1); 177 | 178 | default: 179 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, protocolerror); 180 | return(1); 181 | } 182 | 183 | /* 184 | * Now attempt a serious authentication using the key 185 | */ 186 | SSH2_Auth_PktInit(SSH_MSG_USERAUTH_REQUEST, username); 187 | SSH_putstring("publickey"); 188 | SSH_putbool(1); 189 | SSH_putstring(key->alg->name); 190 | SSH_putuint32(pkblob_len); 191 | SSH_putdata(pkblob, pkblob_len); 192 | 193 | /* The data to be signed is: 194 | * 195 | * string session-id 196 | * 197 | * followed by everything so far placed in the 198 | * outgoing packet. 199 | */ 200 | 201 | sigdata_len = pktout.length + 4 + 32; 202 | if((sigdata = (unsigned char *)malloc(sigdata_len)) == NULL) 203 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 204 | PUT_32BIT_MSB_FIRST(sigdata, 32); 205 | memcpy(sigdata + 4, ssh2_session_id, 32); 206 | memcpy(sigdata + 24, pktout.body, pktout.length); 207 | sigblob = key->alg->sign(key->data, sigdata, sigdata_len, &sigblob_len); 208 | SSH_putuint32(sigblob_len); 209 | SSH_putdata(sigblob, sigblob_len); 210 | free(pkblob); 211 | free(sigblob); 212 | free(sigdata); 213 | SSH_pkt_send(); 214 | 215 | if(SSH2_Auth_Read(SSH_MSG_USERAUTH_SUCCESS)) 216 | return(1); 217 | 218 | return(0); 219 | } 220 | 221 | /* 222 | * Try password authentication, max three times 223 | */ 224 | short SSH2_Auth_Password(char *username, char *password) 225 | { 226 | unsigned short n = 1; 227 | unsigned long j; 228 | char *p; 229 | 230 | if(Configuration & VERBOSE_MODE) 231 | puts("Trying password authentication"); 232 | if(!password){ 233 | printf("Password: "); 234 | fflush(stdout); 235 | if(GlobalConfig.brailab) 236 | fputs("Password: ", GlobalConfig.brailab); 237 | password = AskPassword(); 238 | n++; 239 | } 240 | 241 | nextpass: 242 | SSH2_Auth_PktInit(SSH_MSG_USERAUTH_REQUEST, username); 243 | SSH_putstring("password"); 244 | SSH_putbool(0); 245 | SSH_putstring(password); 246 | SSH_pkt_send(); 247 | free(password); 248 | SendIgnores(); 249 | 250 | restart: 251 | if(SSH2_Auth_Read(0)) 252 | return(1); 253 | 254 | switch(pktin.type) { 255 | case SSH_MSG_USERAUTH_SUCCESS: /* OK */ 256 | break; 257 | 258 | case SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: /* password expired */ 259 | SSH_getstring(&p, &j); 260 | p[j] = 0; 261 | cputs(p); 262 | SSH2_Auth_PktInit(SSH_MSG_USERAUTH_REQUEST, username); 263 | SSH_putstring("password"); 264 | SSH_putbool(1); 265 | SSH_putstring(password); /* old password */ 266 | password = AskPassword(); 267 | SSH_putstring(password); /* new password */ 268 | SSH_pkt_send(); 269 | free(password); 270 | goto restart; 271 | 272 | case SSH_MSG_USERAUTH_FAILURE: /* try again */ 273 | if(n-- == 0){ 274 | SSH_Disconnect(SSH_DISCONNECT_AUTH_CANCELLED_BY_USER, "Invalid password"); 275 | return(1); 276 | } 277 | cputs("Password: "); 278 | if(GlobalConfig.brailab) 279 | fputs("Password: ", GlobalConfig.brailab); 280 | password = AskPassword(); 281 | goto nextpass; 282 | } /* switch */ 283 | return(0); 284 | } 285 | 286 | /* 287 | * Try keyboard interactive authentication, max three times 288 | */ 289 | short SSH2_Auth_KbdInt(char *username, char *password) 290 | { 291 | unsigned short attempts = 3; 292 | unsigned long prompts, i, j; 293 | unsigned char echo; 294 | char *p, *userinputs; 295 | 296 | if(Configuration & VERBOSE_MODE) 297 | puts("Trying keyboard-interactive authentication"); 298 | 299 | nextkbd: 300 | SSH2_Auth_PktInit(SSH_MSG_USERAUTH_REQUEST, username); 301 | SSH_putstring("keyboard-interactive"); 302 | SSH_putstring(""); // language tag 303 | SSH_putstring(""); // submethod 304 | SSH_pkt_send(); 305 | 306 | restartkbd: 307 | if(SSH2_Auth_Read(0)) 308 | return(1); 309 | 310 | switch(pktin.type) { 311 | case SSH_MSG_USERAUTH_SUCCESS: /* OK */ 312 | break; 313 | 314 | case SSH_MSG_USERAUTH_INFO_REQUEST: /* info req */ 315 | SSH_getstring(&p, &j); // name 316 | if(j) 317 | puts(p); 318 | SSH_getstring(&p, &j); // instruction 319 | if(j) 320 | puts(p); 321 | SSH_getstring(&p, &j); // lang tag 322 | prompts = SSH_getuint32(); // num-prompts 323 | if(prompts){ 324 | if((userinputs = (char *)malloc(prompts * 256)) == NULL) 325 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); // 256 per input should be enough 326 | for(i = 0; i < prompts; i++){ 327 | SSH_getstring(&p, &j); // prompt 328 | SSH_getbool(); 329 | if(prompts == 1 && password){ /* try password from command line */ 330 | p = password; 331 | } else { 332 | if(j){ 333 | printf("%s", p); 334 | fflush(stdout); 335 | if(GlobalConfig.brailab){ 336 | fprintf(GlobalConfig.brailab, "%s", p); 337 | } 338 | } 339 | p = AskPassword(); 340 | } 341 | strcpy(userinputs + i * 256, p); 342 | if(prompts >= 1) 343 | free(p); 344 | } 345 | } 346 | SSH_pkt_init(SSH_MSG_USERAUTH_INFO_RESPONSE); 347 | SSH_putuint32(prompts); // num-prompts 348 | if(prompts){ 349 | for(i = 0; i < prompts; i++){ 350 | SSH_putstring(userinputs + i * 256); // put responses 351 | } 352 | free(userinputs); 353 | } 354 | SSH_pkt_send(); 355 | SendIgnores(); 356 | goto restartkbd; 357 | 358 | case SSH_MSG_USERAUTH_FAILURE: /* try again */ 359 | if(--attempts == 0){ 360 | return(1); // password auth comes next 361 | } 362 | goto nextkbd; 363 | } /* switch */ 364 | return(0); 365 | } 366 | 367 | /* 368 | * Initialize an outgoing SSH2 authentication packet. 369 | */ 370 | void SSH2_Auth_PktInit(char type, char *username) 371 | { 372 | SSH_pkt_init(type); 373 | SSH_putstring(username); 374 | SSH_putstring("ssh-connection"); 375 | } 376 | 377 | /* 378 | * Get a packet from the authentication layer. 379 | * If type != NULL, also checks type to avoid protocol confusion 380 | */ 381 | short SSH2_Auth_Read(unsigned char type) 382 | { 383 | char *str; 384 | unsigned long len; 385 | 386 | restart: 387 | if(SSH_pkt_read(0)) /* Get packet from transport layer */ 388 | return(1); 389 | 390 | switch(pktin.type){ 391 | case SSH_MSG_USERAUTH_FAILURE: /* let these through */ 392 | case SSH_MSG_USERAUTH_SUCCESS: 393 | case SSH_MSG_USERAUTH_PK_OK: /* and SSH_MSG_USERAUTH_PASSWD_CHANGEREQ */ 394 | case SSH_MSG_USERAUTH_INFO_RESPONSE: 395 | break; 396 | 397 | case SSH_MSG_USERAUTH_BANNER: /* display banner */ 398 | SSH_getstring(&str, &len); 399 | str[len] = 0; 400 | puts(str); 401 | goto restart; 402 | 403 | default: 404 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, protocolerror); 405 | return(1); 406 | } /* switch */ 407 | 408 | if(type) 409 | if(pktin.type != type){ 410 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, protocolerror); 411 | return(1); 412 | } 413 | return(0); 414 | } 415 | -------------------------------------------------------------------------------- /bin/scp2d386.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/scp2d386.exe -------------------------------------------------------------------------------- /bin/scp2dos.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/scp2dos.exe -------------------------------------------------------------------------------- /bin/sftpd386.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/sftpd386.exe -------------------------------------------------------------------------------- /bin/sftpdos.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/sftpdos.exe -------------------------------------------------------------------------------- /bin/ssh2d386.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/ssh2d386.exe -------------------------------------------------------------------------------- /bin/ssh2dos.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/ssh2dos.exe -------------------------------------------------------------------------------- /bin/tel386.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/tel386.exe -------------------------------------------------------------------------------- /bin/telnet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/bin/telnet.exe -------------------------------------------------------------------------------- /channel.c: -------------------------------------------------------------------------------- 1 | /* channel.c Copyright (c) 2000-2003 Nagy Daniel 2 | * 3 | * $Date: 2005/12/30 16:26:40 $ 4 | * $Revision: 1.3 $ 5 | * 6 | * This module is the connection layer. 7 | * 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 2 12 | * of the License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Library General Public 20 | * License along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "config.h" 29 | #include "macros.h" 30 | #include "ssh.h" 31 | #include "transprt.h" 32 | 33 | /* external functions, data */ 34 | extern Packet pktin; /* incoming SSH2 packet */ 35 | extern unsigned short Configuration; /* configuration bitfields */ 36 | extern char *protocolerror; 37 | 38 | /* local static data */ 39 | static unsigned long local_channel = 1974; /* local channel number */ 40 | static unsigned long remote_channel; /* remote channel number */ 41 | static unsigned long remote_window; /* recipient's window size */ 42 | 43 | /* 44 | * Initialize an outgoing SSH2 channel packet. 45 | */ 46 | void SSH2_Channel_PktInit(unsigned char type) 47 | { 48 | SSH_pkt_init(type); 49 | SSH_putuint32(remote_channel); 50 | } 51 | 52 | /* 53 | * Get a packet from the connection layer. 54 | * If type != NULL, also checks type to avoid protocol confusion 55 | * Returns 1 if: transport layer error 56 | * protocol error 57 | * type is not what we expected 58 | */ 59 | short SSH2_Channel_Read(unsigned char type) 60 | { 61 | char *str; 62 | unsigned long len; 63 | 64 | restart: 65 | if(SSH_pkt_read(0)) /* Get packet from transport layer */ 66 | return(1); 67 | 68 | switch(pktin.type){ 69 | case SSH_MSG_GLOBAL_REQUEST: /* reject all global requests */ 70 | SSH_getstring(&str, &len); 71 | if(SSH_getbool()){ 72 | SSH_pkt_init(SSH_MSG_REQUEST_FAILURE); 73 | SSH_pkt_send(); 74 | } /* if */ 75 | goto restart; 76 | 77 | case SSH_MSG_CHANNEL_OPEN: /* reject channel open requests */ 78 | SSH_getstring(&str, &len); /* dwell channel type */ 79 | len = SSH_getuint32(); /* get channel number */ 80 | SSH_pkt_init(SSH_MSG_CHANNEL_OPEN_FAILURE); 81 | SSH_putuint32(len); 82 | SSH_putuint32(1); /* prohibited */ 83 | SSH_putuint32(0); 84 | SSH_putuint32(0); 85 | SSH_pkt_send(); 86 | goto restart; 87 | 88 | case SSH_MSG_IGNORE: 89 | return(0); 90 | 91 | default: 92 | break; 93 | } /* switch */ 94 | 95 | if(pktin.type < 80 || pktin.type > 100){ /* if not a channel packet */ 96 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, protocolerror); 97 | return(1); 98 | } 99 | 100 | if(SSH_getuint32() != local_channel){ /* if not our channel */ 101 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, "Received data for invalid channel"); 102 | return(1); 103 | } 104 | 105 | switch(pktin.type){ 106 | case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: /* let these through */ 107 | case SSH_MSG_CHANNEL_OPEN_FAILURE: 108 | case SSH_MSG_CHANNEL_SUCCESS: 109 | case SSH_MSG_CHANNEL_FAILURE: 110 | break; 111 | 112 | case SSH_MSG_CHANNEL_DATA: /* adjust window space if data */ 113 | case SSH_MSG_CHANNEL_EXTENDED_DATA: 114 | if(pktin.type == SSH_MSG_CHANNEL_DATA) 115 | len = GET_32BIT_MSB_FIRST(pktin.ptr); 116 | else 117 | len = GET_32BIT_MSB_FIRST(pktin.ptr + 4); 118 | SSH2_Channel_PktInit(SSH_MSG_CHANNEL_WINDOW_ADJUST); 119 | SSH_putuint32(len); 120 | SSH_pkt_send(); 121 | break; 122 | 123 | case SSH_MSG_CHANNEL_WINDOW_ADJUST: /* adjust remote window space */ 124 | remote_window += SSH_getuint32(); 125 | goto restart; 126 | 127 | case SSH_MSG_CHANNEL_EOF: /* Remote sent EOF, dwell it... */ 128 | goto restart; 129 | 130 | case SSH_MSG_CHANNEL_CLOSE: /* Remote closed channel, we close */ 131 | SSH2_Channel_PktInit(SSH_MSG_CHANNEL_CLOSE); 132 | SSH_pkt_send(); 133 | break; 134 | 135 | case SSH_MSG_CHANNEL_REQUEST: /* ignore requests now */ 136 | // FIXME: we may return the exit status code... 137 | // SSH_getstring(&str, &len); /* get request type */ 138 | // if(!strcmp(str, "exit-status") || !strcmp(str, "exit-signal")) 139 | // return status or signal 140 | goto restart; 141 | 142 | default: 143 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, protocolerror); 144 | return(1); 145 | } /* switch */ 146 | 147 | if(type) 148 | if(pktin.type != type){ 149 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, protocolerror); 150 | return(1); 151 | } 152 | return(0); 153 | } 154 | 155 | /* 156 | * Open an SSH2 channel 157 | */ 158 | short SSH2_Channel_Open(void) 159 | { 160 | char *str; 161 | unsigned long len; 162 | 163 | if(Configuration & VERBOSE_MODE) 164 | puts("Opening session channel"); 165 | SSH_pkt_init(SSH_MSG_CHANNEL_OPEN); 166 | SSH_putstring("session"); 167 | SSH_putuint32(local_channel); 168 | SSH_putuint32(MAX_PACKET_SIZE); /* initial local window size */ 169 | SSH_putuint32(MAX_PACKET_SIZE); /* max packet size */ 170 | SSH_pkt_send(); 171 | 172 | if(SSH2_Channel_Read(0)) 173 | return(1); 174 | 175 | switch(pktin.type){ 176 | case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: 177 | remote_channel = SSH_getuint32(); /* remote channel ID */ 178 | remote_window = SSH_getuint32(); /* initial remote window size */ 179 | break; 180 | 181 | case SSH_MSG_CHANNEL_OPEN_FAILURE: 182 | SSH_getuint32(); /* reason code */ 183 | SSH_getstring(&str, &len); 184 | str[len] = '\0'; 185 | puts(str); 186 | return(1); 187 | 188 | default: 189 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, protocolerror); 190 | return(1); 191 | } 192 | return(0); 193 | } 194 | 195 | /* 196 | * Send n data bytes as an SSH packet and shrink remote 197 | * window accordingly 198 | */ 199 | void SSH2_Channel_Send(unsigned char *buff, unsigned short len) 200 | { 201 | /* FIXME: check remote window size before sending data */ 202 | SSH2_Channel_PktInit(SSH_MSG_CHANNEL_DATA); 203 | SSH_putuint32(len); 204 | SSH_putdata(buff, len); 205 | SSH_pkt_send(); 206 | remote_window -=len; 207 | } 208 | -------------------------------------------------------------------------------- /common.c: -------------------------------------------------------------------------------- 1 | /* common.c Copyright (c) 2000-2003 Nagy Daniel 2 | * 3 | * $Date: 2006/03/01 20:37:07 $ 4 | * $Revision: 1.4 $ 5 | * 6 | * Common functions 7 | * 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 2 12 | * of the License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Library General Public 20 | * License along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "tcp.h" 30 | #include "config.h" 31 | #include "proxy.h" 32 | #if defined (MEMWATCH) 33 | #include "memwatch.h" 34 | #endif 35 | 36 | /* external functions, data */ 37 | extern Config GlobalConfig; /* configuration variables */ 38 | extern unsigned short Configuration; /* configuration variables */ 39 | 40 | 41 | /* 42 | * Fatal error handler 43 | */ 44 | void fatal(const char *fmt, ...) 45 | { 46 | va_list ap; 47 | char buf[1024]; 48 | 49 | va_start(ap, fmt); 50 | vsprintf(buf, fmt, ap); 51 | va_end(ap); 52 | puts(buf); 53 | printf("%s", sockerr(&GlobalConfig.s)); 54 | sock_close(&GlobalConfig.s); 55 | exit(255); 56 | } 57 | 58 | 59 | /* 60 | * Try to connect, wait for established 61 | */ 62 | static void doconnect(unsigned long ip, unsigned short rp, unsigned short lp) 63 | { 64 | if(!tcp_open(&GlobalConfig.s, lp, ip, rp, NULL)) 65 | fatal("Unable to open TCP connection"); 66 | 67 | /* Negotiate TCP connection */ 68 | if(Configuration & VERBOSE_MODE) 69 | puts("Waiting for remote host to connect..."); 70 | 71 | while(!sock_established(&GlobalConfig.s)) 72 | if(!tcp_tick(&GlobalConfig.s)) 73 | fatal("Remote host closed connection"); 74 | 75 | return; 76 | } 77 | 78 | 79 | /* 80 | * Parse environment 81 | */ 82 | static void envparse(char *str, char **proxyhost, unsigned short *proxyport, 83 | char **proxyuser, char **proxypass) 84 | { 85 | char *p; 86 | short m, n; 87 | 88 | if((*proxyhost = (char *)malloc(128)) == NULL) 89 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 90 | if(strchr(str, '@')){ /* we have username and maybe password*/ 91 | if((p = *proxyuser = (char *)malloc(32)) == NULL) 92 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 93 | for(n = 0; str[n] != '@' && str[n] != ':'; n++) 94 | p[n] = str[n]; 95 | p[n] = 0; 96 | if(str[n++] == ':'){ /* we have password */ 97 | if((p = *proxypass = (char *)malloc(32)) == NULL) 98 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 99 | for(m = 0; str[n] != '@'; m++, n++) 100 | p[m] = str[n]; 101 | p[m] = 0; 102 | n++; 103 | } 104 | str += n; 105 | } 106 | if((p = strchr(str, ':')) != NULL){ /* we have port specified */ 107 | *p++ = 0; 108 | *proxyport = atoi(p); 109 | } 110 | strcpy(*proxyhost, str); 111 | } 112 | 113 | 114 | /* 115 | * Connect to remote host via TCP 116 | */ 117 | void TCPConnect(char *remotehost, unsigned short remoteport) 118 | { 119 | char *env, method = NOPROXY; 120 | char *proxyuser = NULL, *proxypass = NULL, *proxyhost = NULL; 121 | unsigned short localport, proxyport = 0; 122 | longword remoteip, proxyip; 123 | short n; 124 | 125 | /* Allocate local port */ 126 | localport = (rand() % 512) + 512; 127 | if(Configuration & NONPRIVILEGED_PORT) 128 | localport = localport + 512; 129 | 130 | sock_init(); /* Initialize socket */ 131 | 132 | if((env = getenv("SOCKS_PROXY")) != NULL){ /* we have socks_proxy env.var */ 133 | envparse(env, &proxyhost, &proxyport, &proxyuser, &proxypass); 134 | if(!proxyport) 135 | proxyport = SOCKS_PORT; 136 | method = SOCKS_PROXY; 137 | } else if((env = getenv("HTTP_PROXY")) != NULL){ /* we have http_proxy env.var */ 138 | envparse(env, &proxyhost, &proxyport, &proxyuser, &proxypass); 139 | if(!proxyport) 140 | proxyport = HTTP_PORT; 141 | method = HTTP_PROXY; 142 | } 143 | 144 | if(proxyhost){ /* Resolve proxy */ 145 | if((proxyip = resolve(proxyhost)) == 0) 146 | fatal("Unable to resolve `%s'", proxyhost); 147 | free(proxyhost); 148 | } else { /* Resolve hostname */ 149 | if((remoteip = resolve(remotehost)) == 0) 150 | fatal("Unable to resolve `%s'", remotehost); 151 | } 152 | 153 | switch(method){ 154 | case NOPROXY: 155 | doconnect(remoteip, remoteport, localport); 156 | break; 157 | 158 | case SOCKS_PROXY: 159 | doconnect(proxyip, proxyport, localport); 160 | if(socks5_connect(remotehost, remoteport, proxyuser, proxypass)) 161 | fatal("Failed to begin relaying via SOCKS"); 162 | free(proxyuser); 163 | free(proxypass); 164 | break; 165 | 166 | case HTTP_PROXY: 167 | doconnect(proxyip, proxyport, localport); 168 | n = http_connect(remotehost, remoteport, proxyuser, proxypass); 169 | free(proxyuser); 170 | free(proxypass); 171 | if(n) 172 | fatal("failed to begin relaying via HTTP"); 173 | break; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /contrib/frontend/frontend.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2000 Ken Yap 2 | 3 | ssh is a simple frontend for sshdos that gives you the config file 4 | functionality of the Unix ssh. This functionality could be put into 5 | sshdos but it would make the size of the executable larger. All that is 6 | really needed is a program to read in the command line flags, then parse 7 | a config file, make some subsitutions and finally exec sshdos. 8 | 9 | For example, say the config file ssh.cfg contains this: 10 | 11 | Host sourceforge 12 | Hostname project.sourceforge.net 13 | User programmer 14 | Cipher blowfish 15 | Term linux 16 | Keymap linux.kbd 17 | Mode 132x25 18 | 19 | then you can run ssh like this: 20 | 21 | ssh sourceforge 22 | 23 | and it will call sshdos like this: 24 | 25 | sshdos -c blowfish -t linux -k linux.kbd -m 132x25 programmer project.sourceforge.net 26 | 27 | Like the Unix ssh, it reads options in this order: command line options, 28 | user config file, and finally system config file. The first setting of 29 | an option is the one that takes effect. Wildcards are allowed for the 30 | Host lines, just like the Unix version. Therefore the options should be 31 | arranged from the most specific to the least specific. So in the 32 | previous example, we could override the cipher and user by 33 | 34 | ssh -c 3des writer sourceforge 35 | 36 | and 37 | 38 | sshdos -c 3des writer project.sourceforge.net 39 | 40 | is what gets executed. 41 | 42 | The disadvantage of this approach is that if sshdos gets some new 43 | options, then ssh has to be taught about them. 44 | 45 | (I have made provision for the code to be a frontend for scp later. :-) 46 | 47 | Ken Yap 48 | ken_yap@xoommail.com 49 | August 2000 50 | -------------------------------------------------------------------------------- /contrib/frontend/getopt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * get option letter from argument vector 5 | */ 6 | int opterr = 1, /* useless, never set or used */ 7 | optind = 1, /* index into parent argv vector */ 8 | optopt; /* character checked for validity */ 9 | char *optarg; /* argument associated with option */ 10 | 11 | #define BADCH (int)'?' 12 | #define EMSG "" 13 | #define tell(s) fputs(*nargv,stderr);fputs(s,stderr); \ 14 | fputc(optopt,stderr);fputc('\n',stderr);return(BADCH); 15 | 16 | getopt(nargc,nargv,ostr) 17 | int nargc; 18 | char **nargv, 19 | *ostr; 20 | { 21 | static char *place = EMSG; /* option letter processing */ 22 | register char *oli; /* option letter list index */ 23 | char *strchr(char *, int); 24 | 25 | if(!*place) { /* update scanning pointer */ 26 | if(optind >= nargc || *(place = nargv[optind]) != '-' || 27 | !*++place) return(EOF); 28 | if (*place == '-') { /* found "--" */ 29 | ++optind; 30 | return(EOF); 31 | } 32 | } /* option letter okay? */ 33 | if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) { 34 | if(!*place) ++optind; 35 | tell(": illegal option -- "); 36 | } 37 | if (*++oli != ':') { /* don't need argument */ 38 | optarg = NULL; 39 | if (!*place) ++optind; 40 | } 41 | else { /* need an argument */ 42 | if (*place) optarg = place; /* no white space */ 43 | else if (nargc <= ++optind) { /* no arg */ 44 | place = EMSG; 45 | tell(": option requires an argument -- "); 46 | } 47 | else optarg = nargv[optind]; /* white space */ 48 | place = EMSG; 49 | ++optind; 50 | } 51 | return(optopt); /* dump back option letter */ 52 | } 53 | -------------------------------------------------------------------------------- /contrib/frontend/getopt.h: -------------------------------------------------------------------------------- 1 | int getopt(int argc, char *const *argv, const char *format); 2 | -------------------------------------------------------------------------------- /contrib/frontend/makef386: -------------------------------------------------------------------------------- 1 | CC = wcc 2 | LINK = wcl 3 | 4 | CFLAGS = -ml -0 -fpi -bt=dos -s -i=$(%watcom)\h 5 | 6 | all: .SYMBOLIC 7 | @echo Please specify 'ssh1' or 'ssh2' as target 8 | 9 | ssh1: .SYMBOLIC 10 | $(CC) $(CFLAGS) -DSSHDOS -DSSH386 ssh.c 11 | $(CC) $(CFLAGS) getopt.c 12 | $(CC) $(CFLAGS) regex.c 13 | $(LINK) -l=dos -fe=ssh386.exe ssh.obj getopt.obj regex.obj 14 | 15 | ssh2: .SYMBOLIC 16 | $(CC) $(CFLAGS) -DSSH2DOS -DSSH386 ssh.c 17 | $(CC) $(CFLAGS) getopt.c 18 | $(CC) $(CFLAGS) regex.c 19 | $(LINK) -l=dos -fe=ssh386.exe ssh.obj getopt.obj regex.obj 20 | 21 | clean: .SYMBOLIC 22 | del *.obj 23 | del *.err 24 | del ssh386.exe 25 | -------------------------------------------------------------------------------- /contrib/frontend/makefile: -------------------------------------------------------------------------------- 1 | CC = wcc 2 | LINK = wcl 3 | 4 | CFLAGS = -ml -0 -fpi -bt=dos -s -i=$(%watcom)\h 5 | 6 | all: .SYMBOLIC 7 | @echo Please specify 'ssh1' or 'ssh2' as target 8 | 9 | ssh1: .SYMBOLIC 10 | $(CC) $(CFLAGS) -DSSHDOS ssh.c 11 | $(CC) $(CFLAGS) getopt.c 12 | $(CC) $(CFLAGS) regex.c 13 | $(LINK) -l=dos -fe=ssh.exe ssh.obj getopt.obj regex.obj 14 | 15 | ssh2: .SYMBOLIC 16 | $(CC) $(CFLAGS) -DSSH2DOS ssh.c 17 | $(CC) $(CFLAGS) getopt.c 18 | $(CC) $(CFLAGS) regex.c 19 | $(LINK) -l=dos -fe=ssh.exe ssh.obj getopt.obj regex.obj 20 | 21 | clean: .SYMBOLIC 22 | del *.obj 23 | del *.err 24 | del ssh.exe 25 | -------------------------------------------------------------------------------- /contrib/frontend/regex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * regex.h : External defs for Ozan Yigit's regex functions, for systems 3 | * that don't have them builtin. See regex.c for copyright and other 4 | * details. 5 | * 6 | * Note that this file can be included even if we're linking against the 7 | * system routines, since the interface is (deliberately) identical. 8 | * 9 | * George Ferguson, ferguson@cs.rochester.edu, 11 Sep 1991. 10 | */ 11 | 12 | #ifndef _REGEX_H 13 | #define _REGEX_H 14 | 15 | extern char *re_comp (char *pattern); 16 | extern int re_exec (char *lp); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /contrib/frontend/ssh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Frontend to sshdos 3 | * Reads options and config file and calls sshdos appropriately. 4 | * GPLed by Ken Yap, 2000 5 | * 6 | * $Date: 2005/12/31 10:11:33 $ 7 | * $Revision: 1.3 $ 8 | * 9 | * 2000-08-30 10 | * 2000-08-30 Added regex matching for hostnames 11 | * 2000-08-31 Use __TURBOC__ so tc2.0 can compile 12 | * Undef DEBUGs to silence most output 13 | * 2000-09-02 Add -t option 14 | * Handle null user: @host sanely 15 | * 2000-09-21 Slightly modified by Nagy Daniel: 16 | * added 'Term' option to config file 17 | * 2000-10-16 Pass trailing args to sshdos so that 18 | * they can be treated as command args 19 | * 2001-04-04 Added -s option 20 | * 2002-02-11 Added -n and -k option 21 | * 2002-03-21 Added -C option 22 | * 2003-05-20 Added -m option 23 | * 2003-11-05 OpenWatcom port (removed DJGPP and BORLAND) 24 | * 2003-11-26 Support for separate SSH1 and SSh2 port 25 | * added 'Mode' option to config file 26 | * added -g option 27 | * 28 | * Need to fix: Host lines can have more than one value 29 | */ 30 | 31 | #undef DEBUG_CONFIG 32 | #undef DEBUG_REGEX 33 | #define DEBUG_EXEC 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "getopt.h" 41 | #define strcasecmp(a,b) stricmp(a,b) 42 | 43 | #include "regex.h" 44 | 45 | /*#define SYSCONFDIR "\\etc" */ 46 | #if defined (SSHDOS) 47 | #define USERCONFIGFILE "ssh1.cfg" 48 | #elif defined (SSH2DOS) 49 | #define USERCONFIGFILE "ssh2.cfg" 50 | #endif 51 | 52 | char *sysconfigfile; 53 | 54 | #if defined (SSHDOS) 55 | char *cipher = 0; 56 | #elif defined (SSH2DOS) 57 | int dhgroup = 0; 58 | #endif 59 | char *user = 0; 60 | char *port = 0; 61 | char *host = 0; 62 | char *term = 0; 63 | char *vidmode = 0; 64 | char *keymap = 0; 65 | char *mode = 0; 66 | int privport = -1; 67 | int supressstatus = 0; 68 | int compression = 0; 69 | int addCR = 0; 70 | char *password = 0; 71 | 72 | int newargc = 0; 73 | char *newargv[32]; /* make sure this is enough for all new args */ 74 | #define NARGS (sizeof(newargv)/sizeof(newargv[0])) 75 | 76 | void scanconfig(const char *file, char *host); 77 | void dumpargv(char *argv[]); 78 | 79 | #ifdef SCP_FRONTEND 80 | int main(int argc, char **argv) 81 | { 82 | printf("scp frontend not ready\n"); 83 | exit(0); 84 | } 85 | #else 86 | int main(int argc, char **argv) 87 | { 88 | int c, i, j; 89 | char *p; 90 | extern int optind; 91 | extern char *optarg; 92 | 93 | #ifdef SYSCONFDIR 94 | sysconfigfile = SYSCONFDIR "\\USERCONFIGFILE"; 95 | #else 96 | /* overestimate, but play safe, not dependent on name of executable */ 97 | sysconfigfile = malloc(strlen(argv[0]) + sizeof("\\USERCONFIGFILE")); 98 | if (sysconfigfile == 0) /* out of memory!? */ 99 | exit(1); 100 | strcpy(sysconfigfile, argv[0]); 101 | if ((p = strrchr(sysconfigfile, '\\')) == 0) 102 | p = sysconfigfile; 103 | strcpy(p, "\\USERCONFIGFILE"); 104 | #endif 105 | #if defined (SSHDOS) 106 | while ((c = getopt(argc, argv, "c:l:p:s:t:k:PSCn")) != EOF) { 107 | #elif defined (SSH2DOS) 108 | while ((c = getopt(argc, argv, "l:p:s:t:k:gPSCn")) != EOF) { 109 | #endif 110 | switch (c) { 111 | #if defined (SSHDOS) 112 | case 'c': 113 | cipher = optarg; 114 | break; 115 | #elif defined (SSH2DOS) 116 | case 'g': 117 | dhgroup = 1; 118 | break; 119 | #endif 120 | case 'l': 121 | user = optarg; 122 | break; 123 | case 'p': 124 | port = optarg; 125 | break; 126 | case 's': 127 | password = optarg; 128 | break; 129 | case 't': 130 | term = optarg; 131 | break; 132 | case 'k': 133 | keymap = optarg; 134 | break; 135 | case 'm': 136 | mode = optarg; 137 | break; 138 | case 'P': 139 | privport = 1; 140 | break; 141 | case 'S': 142 | supressstatus = 1; 143 | break; 144 | 145 | case 'C': 146 | compression = 1; 147 | break; 148 | 149 | case 'n': 150 | addCR = 1; 151 | break; 152 | 153 | default: 154 | fprintf(stderr, "Unknown option %c\n", c); 155 | break; 156 | } 157 | } 158 | argc -= optind; 159 | argv += optind; 160 | if (argc <= 0) { 161 | fprintf(stderr, "Usage: ssh [options] host|user@host [command [args]]\n"); 162 | exit(1); 163 | } 164 | host = argv[0]; 165 | argv++; argc--; 166 | if ((p = strchr(host, '@')) != 0) { 167 | user = host; 168 | *p = '\0'; /* user@host will override -l user */ 169 | if (*user == '\0') 170 | user = 0; /* simplify to one case */ 171 | host = p + 1; 172 | } 173 | scanconfig(USERCONFIGFILE, host); 174 | scanconfig(sysconfigfile, host); 175 | #if defined (SSHDOS) 176 | #if defined (SSH386) 177 | newargv[0] = "sshd386"; 178 | #else 179 | newargv[0] = "sshdos"; 180 | #endif 181 | #elif defined (SSH2DOS) 182 | #if defined (SSH386) 183 | newargv[0] = "ssh2d386"; 184 | #else 185 | newargv[0] = "ssh2dos"; 186 | #endif 187 | #endif 188 | i = 1; 189 | #if defined (SSHDOS) 190 | if (cipher) { 191 | newargv[i++] = "-c"; 192 | newargv[i++] = cipher; 193 | } 194 | #elif defined (SSH2DOS) 195 | if (dhgroup) 196 | newargv[i++] = "-g"; 197 | #endif 198 | 199 | if (port) { 200 | newargv[i++] = "-p"; 201 | newargv[i++] = port; 202 | } 203 | if (password) { 204 | newargv[i++] = "-s"; 205 | newargv[i++] = password; 206 | } 207 | if (term) { 208 | newargv[i++] = "-t"; 209 | newargv[i++] = term; 210 | } 211 | if (keymap) { 212 | newargv[i++] = "-k"; 213 | newargv[i++] = keymap; 214 | } 215 | if (mode) { 216 | newargv[i++] = "-m"; 217 | newargv[i++] = mode; 218 | } 219 | if (privport > 0) 220 | newargv[i++] = "-P"; 221 | if (supressstatus) 222 | newargv[i++] = "-S"; 223 | if (compression) 224 | newargv[i++] = "-C"; 225 | if (addCR) 226 | newargv[i++] = "-n"; 227 | if (user) 228 | newargv[i++] = user; 229 | newargv[i++] = host; 230 | /* append command args if any */ 231 | for (j = 0; i < NARGS - 1 && j < argc; j++) 232 | newargv[i++] = argv[j]; 233 | newargv[i] = 0; 234 | #ifdef DEBUG_EXEC 235 | dumpargv(newargv); 236 | #endif 237 | #if defined (SSHDOS) 238 | #if defined (SSH386) 239 | execvp("sshd386", newargv); 240 | perror("sshd386"); 241 | #else 242 | execvp("sshdos", newargv); 243 | perror("sshdos"); 244 | #endif 245 | #elif defined (SSH2DOS) 246 | #if defined (SSH386) 247 | execvp("ssh2d386", newargv); 248 | perror("ssh2d386"); 249 | #else 250 | execvp("ssh2dos", newargv); 251 | perror("ssh2dos"); 252 | #endif 253 | #endif 254 | return(0); 255 | } 256 | #endif /* SCP_FRONTEND */ 257 | 258 | /* 259 | * Read up to bufsiz-1 characters from line 260 | * discarding excess until \n or EOF. 261 | * Terminates string with \0 262 | */ 263 | char *getline(FILE *f, char *buffer, int bufsiz) { 264 | int c; 265 | char *p = buffer; 266 | 267 | while ((c = fgetc(f)) != EOF && c != '\n') { 268 | if (c == '\r') 269 | continue; 270 | if (p != &buffer[bufsiz-1]) 271 | *p++ = c; 272 | } 273 | *p = '\0'; 274 | return (c == EOF ? NULL : buffer); 275 | } 276 | 277 | int iscomment(const char *line) 278 | { 279 | while (isspace(*line)) 280 | line++; 281 | return (*line == '\0' || *line == '#'); 282 | } 283 | 284 | int splitline(char *line, char **key, char **value) 285 | { 286 | char *keyend; 287 | 288 | while (isspace(*line)) 289 | line++; 290 | if (*line == '\0') 291 | return (0); 292 | *key = line; 293 | while (*line != '\0' && !isspace(*line)) 294 | line++; 295 | if (*line == '\0') 296 | return (0); 297 | keyend = line; /* save end position */ 298 | while (isspace(*line)) 299 | line++; 300 | if (*line == '\0') 301 | return (0); 302 | *value = line; 303 | while (*line != '\0' && !isspace(*line)) 304 | line++; 305 | *keyend = '\0'; /* terminate key argument */ 306 | *line = '\0'; /* terminate value argument */ 307 | return (1); 308 | } 309 | 310 | int matchname(char *host, char *pattern) 311 | { 312 | char *pat, *p, *q; 313 | int i; 314 | 315 | if ((pat = malloc(strlen(pattern)*2+2)) == 0) /* twice and ^$ */ 316 | return (0); /* no free space */ 317 | /* convert primitive ssh host patern to what re_comp wants */ 318 | p = pat; 319 | *p++ = '^'; /* put BOL at beginning */ 320 | for (q = pattern; *q != '\0'; p++, q++) { 321 | if (strchr(".\\[]+^$", *q) != 0) /* escape these */ 322 | *p++ = '\\'; 323 | else if (*q == '*') 324 | *p++ = '.'; /* * -> .* */ 325 | else if (*q == '?') { /* ? -> . */ 326 | *p++ = '.'; 327 | continue; 328 | } 329 | *p = *q; 330 | } 331 | *p++ = '$'; /* put EOL at end */ 332 | *p = '\0'; 333 | #ifdef DEBUG_REGEX 334 | printf("regex: %s\n", pat); 335 | #endif 336 | if ((p = re_comp(pat)) != NULL){/* not reentrant, NFA is static data */ 337 | fprintf(stderr, "re_comp: %s\n", p); 338 | free(pat); 339 | return (0); 340 | } 341 | i = re_exec(host); 342 | free(pat); 343 | return (i == 1); /* 0 -> fail, -1 -> error */ 344 | } 345 | 346 | void setvalue(const char *key, const char *value) 347 | { 348 | if (strcasecmp(key, "Hostname") == 0) { 349 | host = strdup(value); /* overwrite hostname */ 350 | } else if (strcasecmp(key, "Port") == 0) { 351 | if (port == 0) /* only if no -p port */ 352 | port = strdup(value); 353 | } 354 | #if defined (SSHDOS) 355 | else if (strcasecmp(key, "Cipher") == 0) { 356 | if (cipher == 0) /* only if no -c cipher */ 357 | cipher = strdup(value); 358 | } 359 | #endif 360 | else if (strcasecmp(key, "Term") == 0) { 361 | if (term == 0) /* only if no -t terminal */ 362 | term = strdup(value); 363 | } else if (strcasecmp(key, "Keymap") == 0) { 364 | if (keymap == 0)/* only if no -k keymap */ 365 | keymap = strdup(value); 366 | } else if (strcasecmp(key, "Mode") == 0) { 367 | if (mode == 0)/* only if no -m mode */ 368 | mode = strdup(value); 369 | } else if (strcasecmp(key, "User") == 0) { 370 | if (user == 0) /* only if no user specified */ 371 | user = strdup(value); 372 | } else if (strcasecmp(key, "UsePrivilegedPort") == 0) { 373 | if (privport < 0) /* only if no -P */ 374 | privport = strcmp(value, "yes") == 0 ? 1 : 375 | strcmp(value, "no") ? 0 : -1; 376 | } 377 | } 378 | 379 | void scanconfig(const char *file, char *host) 380 | { 381 | FILE *f; 382 | int sectionmatches = 0; 383 | char line[256]; 384 | char *key, *value; 385 | 386 | if ((f = fopen(file, "r")) == NULL) 387 | return; 388 | while (getline(f, line, sizeof(line)) != NULL) { 389 | if (iscomment(line)) 390 | continue; 391 | if (splitline(line, &key, &value) == 0) 392 | continue; 393 | #ifdef DEBUG_CONFIG 394 | printf("%s=%s\n", key, value); 395 | #endif 396 | if (strcasecmp(key, "Host") == 0) { 397 | sectionmatches = matchname(host, value); 398 | continue; 399 | } 400 | if (!sectionmatches) 401 | continue; 402 | setvalue(key, value); 403 | } 404 | fclose(f); 405 | } 406 | 407 | void dumpargv(char *argv[]) 408 | { 409 | char *p; 410 | 411 | printf("Command:"); 412 | for (p = *argv++; p != 0; p = *argv++) 413 | printf(" %s", p); 414 | printf("\n"); 415 | } 416 | -------------------------------------------------------------------------------- /contrib/frontend/ssh1.cfg: -------------------------------------------------------------------------------- 1 | # this is a sample configuration file 2 | 3 | # host definition begins 4 | Host samplehost 5 | Hostname sample.host.com # full hostname 6 | # Port 22 # remote port 7 | User sampleuser # username 8 | Cipher blowfish # cipher type 9 | Term linux # terminal type 10 | Keymap linux.kbd # keymap file 11 | # Mode 132x50 # video mode 12 | # UsePrivilegedPort yes # use privileged port 13 | -------------------------------------------------------------------------------- /contrib/frontend/ssh2.cfg: -------------------------------------------------------------------------------- 1 | # this is a sample configuration file 2 | 3 | # host definition begins 4 | Host samplehost 5 | Hostname sample.host.com # full hostname 6 | # Port 22 # remote port 7 | User sampleuser # username 8 | Term linux # terminal type 9 | Keymap linux.kbd # keymap file 10 | # Mode 132x50 # video mode 11 | # UsePrivilegedPort yes # use privileged port 12 | -------------------------------------------------------------------------------- /contrib/keycodes/keycodes.asm: -------------------------------------------------------------------------------- 1 | ; keycode.asm 2 | ; 3 | ; Utility to print the keyboard code of a pressed key 4 | ; 5 | ; Compilation: nasm -f bin -o keycodes.com keycodes.asm 6 | ; 7 | ; 8 | ; This program is free software; you can redistribute it and/or 9 | ; modify it under the terms of the GNU General Public License 10 | ; as published by the Free Software Foundation; either version 2 11 | ; of the License, or (at your option) any later version. 12 | ; 13 | ; This program is distributed in the hope that it will be useful, 14 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ; GNU General Public License for more details. 17 | ; 18 | ; You should have received a copy of the GNU Library General Public 19 | ; License along with this program; if not, write to the Free Software 20 | ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | BITS 16 23 | ORG 0x100 24 | RUN: 25 | MOV DX,MSG_1 ; print message 26 | MOV AH,09H 27 | INT 21H 28 | LAB1: 29 | MOV AH,10H ; wait for a keystroke 30 | INT 16H 31 | 32 | PUSH AX 33 | MOV DX,AX ; convert it to human-readable 34 | MOV CX,4 35 | MOV BX,CX 36 | LAB2: 37 | MOV AX,DX 38 | AND AL,0FH 39 | CMP AL,10 40 | JB LAB3 41 | ADD AL,7 42 | LAB3: 43 | ADD AL,30H 44 | MOV [MSG_2_KEY+BX-1],AL 45 | SHR DX,CL 46 | DEC BX 47 | JNZ LAB2 48 | 49 | MOV DX,MSG_2 ; print it 50 | MOV AH,09H 51 | INT 21H 52 | POP AX 53 | 54 | CMP AX,011BH ; jump back if not ESC 55 | JNZ LAB1 56 | 57 | EXIT: 58 | MOV AX,4C00H ; quit 59 | INT 21H 60 | 61 | 62 | MSG_1 DB "KeyCodes test = 0x011B - exit.", 0Dh, 0AH, "$" 63 | MSG_2 DB "keycode = 0x" 64 | MSG_2_KEY DB "0000", 0DH, 0AH, "$" 65 | -------------------------------------------------------------------------------- /docs/bugs: -------------------------------------------------------------------------------- 1 | - ? -------------------------------------------------------------------------------- /docs/history: -------------------------------------------------------------------------------- 1 | v0.2.1+SHA256.1 - removed diffie-hellman-group1-sha1 2 | - added diffie-hellman-group14-sha256 3 | - removed aes128-cbc 4 | - added aes128-ctr 5 | - removed hmac-sha1 6 | - added hmac-sha2-256 7 | 8 | v0.2.1 - Added vt340.kbd for VT340 emulation 9 | - Real-mode binary should work on 8086 processors 10 | - Mode switching bug is fixed in non-vesa modes 11 | 12 | v0.2.0 - Added SOCKS5 and HTTP proxy support 13 | - Added keyboard-interactive authentication method 14 | - Added scp support 15 | 16 | v0.1.1 - bugfix release for the 'too large packet' problem 17 | 18 | v0.1.0 - by Przemyslaw Czerpak : 19 | - checking the real screen size (width and high) for VGA 20 | - corrected bug in cursor hide/show: ESC [ ? 25 h/l 21 | - added cursor shape codes ESC [ ? n c 22 | - added set / restore color palette codes ESC ] R, ESC ] P nnrrggbb 23 | - New codes from linux console 24 | - even more terminal fixes 25 | - support for 80x60, 132x25 and 132x50 video modes (VESA required) 26 | - added scrollback support 27 | - code cleanup 28 | - changed to OpenWatcom (DJGPP and Borland support removed) 29 | - added support for Diffie-Hellman group key exchange 30 | - added SCP utility 31 | 32 | v0.0.1 - First public release, based on the SSHDOS source, so it should be 33 | stable and usable. SFTP also included, thanks to PuTTY 34 | -------------------------------------------------------------------------------- /docs/readme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/docs/readme -------------------------------------------------------------------------------- /docs/todo: -------------------------------------------------------------------------------- 1 | - more simultaneous sessions, Linux-like ALT-Fx 2 | - mouse cut&paste 3 | - key reexchange test 4 | - fatal more verbose 5 | - make ALT keys and scrollback optional 6 | -------------------------------------------------------------------------------- /include/auth.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUTH_H 2 | #define _AUTH_H 3 | 4 | extern void SSH2_Auth_PktInit(char, char *); 5 | extern short SSH2_Auth_Read(unsigned char); 6 | extern short SSH2_Auth_Pubkey(char *, char *); 7 | extern short SSH2_Auth_Password(char *, char *); 8 | extern short SSH2_Auth_KbdInt(char *, char *); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/channel.h: -------------------------------------------------------------------------------- 1 | #ifndef _CHANNEL_H 2 | #define _CHANNEL_H 3 | 4 | extern void SSH2_Channel_PktInit(unsigned char); 5 | extern short SSH2_Channel_Read(unsigned char); 6 | extern void SSH2_Channel_Send(unsigned char *, unsigned short); 7 | extern short SSH2_Channel_Open(void); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMMON_H 2 | #define _COMMON_H 3 | 4 | extern void fatal(const char *fmt, ...); 5 | extern void TCPConnect(char *remotehost, unsigned short remoteport); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H 2 | #define _CONFIG_H 3 | 4 | #include "tcp.h" 5 | 6 | typedef void (*SendFuncPtr)(char *, unsigned short); 7 | 8 | #define MAX_PASSWORD_LENGTH 30 9 | 10 | /* Configuration options */ 11 | typedef struct { 12 | char *identity; 13 | tcp_Socket s; 14 | FILE *debugfile; 15 | FILE *brailab; 16 | FILE *batchfile; 17 | } Config; 18 | 19 | /* Configuration options stored in bits */ 20 | #define CIPHER_ENABLED 1 21 | #define PRESERVE_ATTRIBUTES 2 22 | #define RECURSIVE_COPY 4 23 | #define VERBOSE_MODE 8 24 | #define QUIET_MODE 16 25 | #define COMPRESSION_REQUESTED 32 26 | #define COMPRESSION_ENABLED 64 27 | #define NONPRIVILEGED_PORT 128 28 | #define NEWLINE 256 29 | #define CONVERT_LOWERCASE 512 30 | #define BIOS 1024 31 | #define SFTP_CONNECTED 2048 32 | #define NOVESA 4096 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/int64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header for int64.c. 3 | */ 4 | 5 | #ifndef PUTTY_INT64_H 6 | #define PUTTY_INT64_H 7 | 8 | typedef struct { 9 | unsigned long hi, lo; 10 | } uint64, int64; 11 | 12 | extern uint64 uint64_div10(uint64 x, int *remainder); 13 | extern void uint64_decimal(uint64 x, char *buffer); 14 | extern uint64 uint64_make(unsigned long hi, unsigned long lo); 15 | extern uint64 uint64_add(uint64 x, uint64 y); 16 | extern uint64 uint64_add32(uint64 x, unsigned long y); 17 | extern int uint64_compare(uint64 x, uint64 y); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/keyio.h: -------------------------------------------------------------------------------- 1 | #ifndef _KEYIO_H 2 | #define _KEYIO_H 3 | 4 | extern int ConChk(void); /* Check the keyboard for keystrokes */ 5 | extern void DoKey(void); /* Interpret a keypress */ 6 | extern void SetKeyPad(int); /* Set the keypad to APPLICATION, NUMERIC */ 7 | extern void SetCursorKey(int); /* Set the cursor key mode */ 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/keymap.h: -------------------------------------------------------------------------------- 1 | #ifndef _KEYMAP_H 2 | #define _KEYMAP_H 3 | 4 | extern char *keymap_value(unsigned int scancode); 5 | extern void keymap_init(const char *filename); 6 | extern void keymap_uninit(void); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef _MACROS_H 2 | #define _MACROS_H 3 | 4 | /* Common macros */ 5 | 6 | #define GET_32BIT_LSB_FIRST(cp) \ 7 | (((unsigned long)(unsigned char)(cp)[0]) | \ 8 | ((unsigned long)(unsigned char)(cp)[1] << 8) | \ 9 | ((unsigned long)(unsigned char)(cp)[2] << 16) | \ 10 | ((unsigned long)(unsigned char)(cp)[3] << 24)) 11 | 12 | #define PUT_32BIT_LSB_FIRST(cp, value) ( \ 13 | (cp)[0] = (value), \ 14 | (cp)[1] = (unsigned long)(value) >> 8, \ 15 | (cp)[2] = (unsigned long)(value) >> 16, \ 16 | (cp)[3] = (unsigned long)(value) >> 24 ) 17 | 18 | #define GET_32BIT_MSB_FIRST(cp) \ 19 | (((unsigned long)(unsigned char)(cp)[3]) | \ 20 | ((unsigned long)(unsigned char)(cp)[2] << 8) | \ 21 | ((unsigned long)(unsigned char)(cp)[1] << 16) | \ 22 | ((unsigned long)(unsigned char)(cp)[0] << 24)) 23 | 24 | #define PUT_32BIT_MSB_FIRST(cp, value) ( \ 25 | (cp)[0] = (unsigned long)(value) >> 24, \ 26 | (cp)[1] = (unsigned long)(value) >> 16, \ 27 | (cp)[2] = (unsigned long)(value) >> 8, \ 28 | (cp)[3] = (value) ) 29 | 30 | #define PUT_16BIT_MSB_FIRST(cp, value) ( \ 31 | (cp)[0] = (value) >> 8, \ 32 | (cp)[1] = (value) ) 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/negotiat.h: -------------------------------------------------------------------------------- 1 | #ifndef _NEGOTIAT_H 2 | #define _NEGOTIAT_H 3 | 4 | extern void SSH_Connect(char *username, char *password, char *keyfile); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/proxy.h: -------------------------------------------------------------------------------- 1 | #ifndef _PROXY_H 2 | #define _PROXY_H 3 | 4 | #define NOPROXY 0 5 | #define SOCKS_PROXY 1 6 | #define HTTP_PROXY 2 7 | #define SOCKS_PORT 1080 8 | #define HTTP_PORT 3128 9 | 10 | extern short socks5_connect(char *remotehost, unsigned short remoteport, 11 | char *proxyuser, char *proxypass); 12 | 13 | extern short http_connect(char *remotehost, unsigned short remoteport, 14 | char *proxyuser, char *proxypass); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /include/pubkey.h: -------------------------------------------------------------------------------- 1 | #ifndef _PUBKEY_H 2 | #define _PUBKEY_H 3 | 4 | enum { OSSH_DSA, OSSH_RSA }; 5 | struct openssh_key { 6 | int type; 7 | int encrypted; 8 | char iv[32]; 9 | unsigned char *keyblob; 10 | int keyblob_len, keyblob_size; 11 | }; 12 | 13 | struct ssh_signkey { 14 | unsigned char *(*public_blob) (void *, int *); 15 | void *(*createkey) (unsigned char *, int , unsigned char *, int); 16 | unsigned char *(*sign) (void *, char *, int, int *); 17 | char *name; 18 | }; 19 | 20 | struct ssh2_userkey { 21 | const struct ssh_signkey *alg; /* the key algorithm */ 22 | void *data; /* the key data */ 23 | char *comment; /* the key comment */ 24 | }; 25 | 26 | #define SSH2_WRONG_PASSPHRASE (&ssh2_wrong_passphrase) 27 | 28 | int key_type(char *); 29 | char *ssh2_userkey_loadpub(char *, char **, int *); 30 | int ssh2_userkey_encrypted(char *, char **); 31 | struct ssh2_userkey *ssh2_load_userkey(char *, char *); 32 | int openssh_encrypted(char *); 33 | struct ssh2_userkey *openssh_read(char *, char *); 34 | 35 | char *key_type_to_str(int); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/sftp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sftp.h: definitions for SFTP and the sftp.c routines. 3 | */ 4 | 5 | #include "int64.h" 6 | 7 | #define TRANSBUF_SIZE 4096 8 | 9 | #define SSH_FXP_INIT 1 /* 0x1 */ 10 | #define SSH_FXP_VERSION 2 /* 0x2 */ 11 | #define SSH_FXP_OPEN 3 /* 0x3 */ 12 | #define SSH_FXP_CLOSE 4 /* 0x4 */ 13 | #define SSH_FXP_READ 5 /* 0x5 */ 14 | #define SSH_FXP_WRITE 6 /* 0x6 */ 15 | #define SSH_FXP_LSTAT 7 /* 0x7 */ 16 | #define SSH_FXP_FSTAT 8 /* 0x8 */ 17 | #define SSH_FXP_SETSTAT 9 /* 0x9 */ 18 | #define SSH_FXP_FSETSTAT 10 /* 0xa */ 19 | #define SSH_FXP_OPENDIR 11 /* 0xb */ 20 | #define SSH_FXP_READDIR 12 /* 0xc */ 21 | #define SSH_FXP_REMOVE 13 /* 0xd */ 22 | #define SSH_FXP_MKDIR 14 /* 0xe */ 23 | #define SSH_FXP_RMDIR 15 /* 0xf */ 24 | #define SSH_FXP_REALPATH 16 /* 0x10 */ 25 | #define SSH_FXP_STAT 17 /* 0x11 */ 26 | #define SSH_FXP_RENAME 18 /* 0x12 */ 27 | #define SSH_FXP_STATUS 101 /* 0x65 */ 28 | #define SSH_FXP_HANDLE 102 /* 0x66 */ 29 | #define SSH_FXP_DATA 103 /* 0x67 */ 30 | #define SSH_FXP_NAME 104 /* 0x68 */ 31 | #define SSH_FXP_ATTRS 105 /* 0x69 */ 32 | #define SSH_FXP_EXTENDED 200 /* 0xc8 */ 33 | #define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */ 34 | 35 | #define SSH_FX_OK 0 36 | #define SSH_FX_EOF 1 37 | #define SSH_FX_NO_SUCH_FILE 2 38 | #define SSH_FX_PERMISSION_DENIED 3 39 | #define SSH_FX_FAILURE 4 40 | #define SSH_FX_BAD_MESSAGE 5 41 | #define SSH_FX_NO_CONNECTION 6 42 | #define SSH_FX_CONNECTION_LOST 7 43 | #define SSH_FX_OP_UNSUPPORTED 8 44 | 45 | #define SSH_FILEXFER_ATTR_SIZE 0x00000001 46 | #define SSH_FILEXFER_ATTR_UIDGID 0x00000002 47 | #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004 48 | #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008 49 | #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000 50 | 51 | #define SSH_FXF_READ 0x00000001 52 | #define SSH_FXF_WRITE 0x00000002 53 | #define SSH_FXF_APPEND 0x00000004 54 | #define SSH_FXF_CREAT 0x00000008 55 | #define SSH_FXF_TRUNC 0x00000010 56 | #define SSH_FXF_EXCL 0x00000020 57 | 58 | #define SFTP_PROTO_VERSION 3 59 | 60 | struct fxp_attrs { 61 | unsigned long flags; 62 | uint64 size; 63 | unsigned long uid; 64 | unsigned long gid; 65 | unsigned long permissions; 66 | unsigned long atime; 67 | unsigned long mtime; 68 | }; 69 | 70 | struct fxp_handle { 71 | char *hstring; 72 | int hlen; 73 | }; 74 | 75 | struct fxp_name { 76 | char *filename, *longname; 77 | struct fxp_attrs attrs; 78 | }; 79 | 80 | struct fxp_names { 81 | int nnames; 82 | struct fxp_name *names; 83 | }; 84 | 85 | const char *fxp_error(void); 86 | int fxp_error_type(void); 87 | 88 | /* 89 | * Perform exchange of init/version packets. Return 0 on failure. 90 | */ 91 | int fxp_init(void); 92 | 93 | /* 94 | * Canonify a pathname. Concatenate the two given path elements 95 | * with a separating slash, unless the second is NULL. 96 | */ 97 | char *fxp_realpath(char *path); 98 | 99 | /* 100 | * Open a file. 101 | */ 102 | struct fxp_handle *fxp_open(char *path, int type); 103 | 104 | /* 105 | * Open a directory. 106 | */ 107 | struct fxp_handle *fxp_opendir(char *path); 108 | 109 | /* 110 | * Close a file/dir. 111 | */ 112 | void fxp_close(struct fxp_handle *handle); 113 | 114 | /* 115 | * Make a directory. 116 | */ 117 | int fxp_mkdir(char *path); 118 | 119 | /* 120 | * Remove a directory. 121 | */ 122 | int fxp_rmdir(char *path); 123 | 124 | /* 125 | * Remove a file. 126 | */ 127 | int fxp_remove(char *fname); 128 | 129 | /* 130 | * Rename a file. 131 | */ 132 | int fxp_rename(char *srcfname, char *dstfname); 133 | 134 | /* 135 | * Return file attributes. 136 | */ 137 | int fxp_stat(char *fname, struct fxp_attrs *attrs); 138 | int fxp_fstat(struct fxp_handle *handle, struct fxp_attrs *attrs); 139 | 140 | /* 141 | * Set file attributes. 142 | */ 143 | int fxp_setstat(char *fname, struct fxp_attrs attrs); 144 | int fxp_fsetstat(struct fxp_handle *handle, struct fxp_attrs attrs); 145 | 146 | /* 147 | * Read from a file. 148 | */ 149 | int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, 150 | int len); 151 | 152 | /* 153 | * Write to a file. Returns 0 on error, 1 on OK. 154 | */ 155 | int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset, 156 | int len); 157 | 158 | /* 159 | * Read from a directory. 160 | */ 161 | struct fxp_names *fxp_readdir(struct fxp_handle *handle); 162 | 163 | /* 164 | * Free up an fxp_names structure. 165 | */ 166 | void fxp_free_names(struct fxp_names *names); 167 | 168 | /* 169 | * Duplicate and free fxp_name structures. 170 | */ 171 | struct fxp_name *fxp_dup_name(struct fxp_name *name); 172 | void fxp_free_name(struct fxp_name *name); 173 | -------------------------------------------------------------------------------- /include/shell.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHELL_H 2 | #define _SHELL_H 3 | 4 | void Shell(void); /* Run DOS shell */ 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/ssh.h: -------------------------------------------------------------------------------- 1 | #ifndef _SSH_H 2 | #define _SSH_H 3 | 4 | /* SSH constants and protocol structure */ 5 | 6 | #define MAX_PACKET_SIZE 8192 /* max packet size */ 7 | #define EXIT_SSH 1381 8 | 9 | #define SSH_PORT 22 10 | 11 | #define SSH_MSG_DISCONNECT 1 12 | #define SSH_MSG_IGNORE 2 13 | #define SSH_MSG_UNIMPLEMENTED 3 14 | #define SSH_MSG_DEBUG 4 15 | #define SSH_MSG_SERVICE_REQUEST 5 16 | #define SSH_MSG_SERVICE_ACCEPT 6 17 | #define SSH_MSG_KEXINIT 20 18 | #define SSH_MSG_NEWKEYS 21 19 | #define SSH_MSG_KEXDH_INIT 30 20 | #define SSH_MSG_KEXDH_REPLY 31 21 | #define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30 22 | #define SSH_MSG_KEX_DH_GEX_GROUP 31 23 | #define SSH_MSG_KEX_DH_GEX_INIT 32 24 | #define SSH_MSG_KEX_DH_GEX_REPLY 33 25 | #define SSH_MSG_KEX_DH_GEX_REQUEST 34 26 | 27 | #define SSH_MSG_USERAUTH_REQUEST 50 28 | #define SSH_MSG_USERAUTH_FAILURE 51 29 | #define SSH_MSG_USERAUTH_SUCCESS 52 30 | #define SSH_MSG_USERAUTH_BANNER 53 31 | #define SSH_MSG_USERAUTH_PK_OK 60 32 | #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60 33 | #define SSH_MSG_USERAUTH_INFO_REQUEST 60 34 | #define SSH_MSG_USERAUTH_INFO_RESPONSE 61 35 | #define SSH_MSG_GLOBAL_REQUEST 80 36 | #define SSH_MSG_REQUEST_SUCCESS 81 37 | #define SSH_MSG_REQUEST_FAILURE 82 38 | #define SSH_MSG_CHANNEL_OPEN 90 39 | #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91 40 | #define SSH_MSG_CHANNEL_OPEN_FAILURE 92 41 | #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93 42 | #define SSH_MSG_CHANNEL_DATA 94 43 | #define SSH_MSG_CHANNEL_EXTENDED_DATA 95 44 | #define SSH_MSG_CHANNEL_EOF 96 45 | #define SSH_MSG_CHANNEL_CLOSE 97 46 | #define SSH_MSG_CHANNEL_REQUEST 98 47 | #define SSH_MSG_CHANNEL_SUCCESS 99 48 | #define SSH_MSG_CHANNEL_FAILURE 100 49 | 50 | /* Major protocol version. Different version indicates major incompatiblity 51 | that prevents communication. */ 52 | #define PROTOCOL_MAJOR 2 53 | 54 | /* Minor protocol version. Different version indicates minor incompatibility 55 | that does not prevent interoperation. */ 56 | #define PROTOCOL_MINOR 0 57 | 58 | enum { 59 | SSH_KEYTYPE_UNOPENABLE, 60 | SSH_KEYTYPE_UNKNOWN, 61 | SSH_KEYTYPE_SSH1, SSH_KEYTYPE_SSH2, 62 | SSH_KEYTYPE_OPENSSH, SSH_KEYTYPE_SSHCOM 63 | }; 64 | 65 | #define SSH_DISCONNECT_PROTOCOL_ERROR 2 66 | #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3 67 | #define SSH_DISCONNECT_MAC_ERROR 5 68 | #define SSH_DISCONNECT_COMPRESSION_ERROR 6 69 | #define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7 70 | #define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 71 | #define SSH_DISCONNECT_CONNECTION_LOST 10 72 | #define SSH_DISCONNECT_BY_APPLICATION 11 73 | #define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /include/sshbn.h: -------------------------------------------------------------------------------- 1 | #ifndef _BN_H 2 | #define _BN_H 3 | 4 | /* Bignum functions */ 5 | 6 | typedef unsigned short *Bignum; 7 | 8 | extern unsigned short ssh1_read_bignum(unsigned char *, Bignum *); 9 | extern unsigned short ssh1_bignum_length(Bignum); 10 | extern unsigned short ssh1_write_bignum(void *, Bignum); 11 | extern Bignum modpow(Bignum, Bignum, Bignum); 12 | extern Bignum modmul(Bignum, Bignum, Bignum); 13 | extern Bignum bigmul(Bignum, Bignum); 14 | extern Bignum bignum_from_bytes(unsigned char *, unsigned short); 15 | extern Bignum copybn(Bignum); 16 | extern unsigned short bignum_bitcount(Bignum); 17 | extern unsigned char bignum_byte(Bignum, unsigned short); 18 | extern short bignum_cmp(Bignum, Bignum); 19 | extern void decbn(Bignum); 20 | extern void freebn(Bignum); 21 | 22 | extern Bignum bignum_bitmask(Bignum); 23 | extern Bignum bignum_rshift(Bignum, unsigned short); 24 | extern Bignum modinv(Bignum, Bignum); 25 | extern Bignum bn_power_2(unsigned short); 26 | extern Bignum bigmod(Bignum, Bignum); 27 | extern Bignum bigmuladd(Bignum, Bignum, Bignum); 28 | extern void bignum_set_bit(Bignum, unsigned short, unsigned short); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/sshmd5.h: -------------------------------------------------------------------------------- 1 | #ifndef _MD5_H 2 | #define _MD5_H 3 | 4 | #include "type.h" 5 | 6 | /* MD5 hash functions */ 7 | 8 | extern void MD5Init(void); 9 | extern void MD5Update(const char *buf, unsigned len); 10 | extern void MD5Final(char digest[16]); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/sshsha.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHA_H 2 | #define _SHA_H 3 | 4 | #include "type.h" 5 | #include "sshbn.h" 6 | #include "int64.h" 7 | 8 | typedef struct { 9 | uint32 h[5]; 10 | unsigned char block[64]; 11 | int blkused; 12 | uint32 lenhi, lenlo; 13 | } SHA_State; 14 | 15 | typedef struct { 16 | uint32 h[8]; 17 | unsigned char block[64]; 18 | int blkused; 19 | uint32 lenhi, lenlo; 20 | } SHA256_State; 21 | 22 | typedef struct { 23 | uint64 h[8]; 24 | unsigned char block[128]; 25 | int blkused; 26 | uint32 len[4]; 27 | } SHA512_State; 28 | 29 | void SHA256_Init(SHA256_State * s); 30 | void SHA256_Bytes(SHA256_State * s, const void *p, int short); 31 | void SHA256_Final(SHA256_State * s, unsigned char *output); 32 | void SHA256_Simple(const void *p, int len, unsigned char *output); 33 | 34 | void SHA512_Init(SHA512_State * s); 35 | void SHA512_Bytes(SHA512_State * s, const void *p, int len); 36 | void SHA512_Final(SHA512_State * s, unsigned char *output); 37 | 38 | void sha1_cskey(unsigned char *); 39 | void sha1_sckey(unsigned char *); 40 | void sha256_cskey(unsigned char *); 41 | void sha256_sckey(unsigned char *); 42 | 43 | void SHA_Init(SHA_State *); 44 | void SHA_Bytes(SHA_State *, void *, short); 45 | void SHA_Final(SHA_State *, unsigned char *); 46 | void SHA_Simple(void *, int, unsigned char *); 47 | void hmac_sha1_simple(void *, int, void *, int, unsigned char *); 48 | 49 | void sha1_generate(unsigned char *, unsigned short, unsigned long); 50 | int sha1_verify(unsigned char *, unsigned short, unsigned long); 51 | 52 | void sha_string(SHA_State *, void *, unsigned long); 53 | unsigned char *ssh2_mpint_fmt(Bignum, unsigned long *); 54 | void sha_mpint(SHA_State *, Bignum); 55 | 56 | void sha256_string(SHA256_State *, void *, unsigned long); 57 | void sha256_mpint(SHA256_State *, Bignum); 58 | void sha256_generate(unsigned char *, unsigned short, unsigned long); 59 | int sha256_verify(unsigned char *, unsigned short, unsigned long); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/telnet.h: -------------------------------------------------------------------------------- 1 | #ifndef _TELNET_H 2 | #define _TELNET_H 3 | 4 | #define IAC 255 /* interpret as command */ 5 | #define DONT 254 /* you are not to use option */ 6 | #define DO 253 /* please, you use option */ 7 | #define WONT 252 /* I won't use option */ 8 | #define WILL 251 /* I will use option */ 9 | #define SB 250 /* interpret as subnegotiation */ 10 | #define BREAK 243 11 | #define SE 240 /* end sub negotiation */ 12 | 13 | #define TELOPT_BINARY 0 /* 8-bit data path */ 14 | #define TELOPT_ECHO 1 /* echo */ 15 | #define TELOPT_SGA 3 /* suppress go ahead */ 16 | #define TELOPT_NAMS 4 /* approximate message size */ 17 | #define TELOPT_STATUS 5 /* give status */ 18 | 19 | #define TELOPT_TTYPE 24 /* terminal type */ 20 | #define TELOPT_NAWS 31 /* window size */ 21 | #define TELOPT_XDISPLOC 35 /* X Display Location */ 22 | #define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ 23 | #define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ 24 | 25 | #define EXIT_TELNET 1382 26 | 27 | #define TSBUFSIZ 41 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/transprt.h: -------------------------------------------------------------------------------- 1 | #ifndef _TRANSPRT_H 2 | #define _TRANSPRT_H 3 | 4 | /* Packet structure */ 5 | 6 | typedef struct { 7 | unsigned long length; /* body length */ 8 | unsigned long maxlen; /* max length */ 9 | unsigned char type; /* packet type */ 10 | unsigned char *whole; /* pointer to whole packet */ 11 | unsigned char *body; /* pointer to useful data */ 12 | unsigned char *ptr; /* sliding pointer in body */ 13 | } Packet; 14 | 15 | /* Initialize important variables */ 16 | void SSH2_init(void); 17 | 18 | /* request compression from server */ 19 | void Request_Compression(int); 20 | 21 | /* free compression memory */ 22 | void Disable_Compression(void); 23 | 24 | /* get a packet from the transport layer */ 25 | short SSH_pkt_read(unsigned char); 26 | 27 | /* create header for raw outgoing packet */ 28 | void SSH_pkt_init(unsigned char); 29 | 30 | /* create outgoing packet */ 31 | void SSH_pkt_send(void); 32 | 33 | /* SSH2 packet assembly */ 34 | void SSH_putuint32(unsigned long); 35 | void SSH_putbool(unsigned char); 36 | void SSH_putstring(unsigned char *); 37 | void SSH_putdata(unsigned char *, unsigned short); 38 | unsigned short SSH_putmp(unsigned short *); 39 | 40 | /* SSH2 packet disassembly */ 41 | unsigned long SSH_getuint32(void); 42 | unsigned int SSH_getbool(void); 43 | void SSH_getstring(char **, unsigned long *); 44 | 45 | /* SSH2 disconnect */ 46 | void SSH_Disconnect(unsigned long, const char *, ...); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/type.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPE_H 2 | #define _TYPE_H 3 | 4 | typedef unsigned long word32; 5 | typedef unsigned long uint32; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/version.h: -------------------------------------------------------------------------------- 1 | #ifndef _VERSION_H 2 | #define _VERSION_H 3 | 4 | /* SSH2DOS version */ 5 | 6 | #define SSH_VERSION "0.2.1+SHA256.1" 7 | #define AUTHOR_1 "SSH2DOS by Daniel Nagy (2000-2006) - http://sshdos.sourceforge.net/" 8 | #define AUTHOR_2 "SHA256 patch by Antti Takala - https://github.com/AnttiTakala/SSH2DOS" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/vidio.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIDIO_H 2 | #define _VIDIO_H 3 | 4 | extern void VidInit(char *, char *); /* Initialize console */ 5 | extern void VidUninit(void); /* Uninitialize console */ 6 | extern void VidParam(void); /* Get Screen Size */ 7 | extern void VESACheck(void); /* Check VESA BIOS */ 8 | extern void SetMode(void); /* Set video mode */ 9 | extern void SbkSetPage(char); 10 | extern void SbkBack(void); 11 | extern void SbkForward(void); 12 | extern void SbkAddline(void); 13 | extern short savescreen(char **p); 14 | extern void restorescreen(char *p, short pos); 15 | extern void SetVattr(unsigned char); /* Set the video attribute */ 16 | extern void AddVattr(unsigned char); /* Add attribute to current video attribute */ 17 | extern void SubVattr(unsigned char); /* Sub attribute from current vid attribute */ 18 | extern void LineRight(void); /* Scroll line to right from cursor */ 19 | extern void ChrWrite(unsigned char); /* Write character to the screen */ 20 | extern void ChrDelete(void); /* Erase character at current position */ 21 | extern void SetScroll(int, int); /* Set the scrolling region */ 22 | extern void ScrollDown(void); /* Move down a row scrolling if necessary */ 23 | extern void ScrollUp(void); /* Move up a row scrolling if necessary */ 24 | extern void IndexDown(void); /* Scroll the screen down */ 25 | extern void IndexUp(void); /* Scroll the screen up */ 26 | extern void SetCurs(int, int); /* Set the cursor to absolute coordinates */ 27 | extern void SetRelCurs(int, int); /* Set the cursor to relative coordinates */ 28 | extern void ClearScreen(void); /* Clear the terminal screen */ 29 | extern void ClearEOS(void); /* Clear from cursor to end of screen */ 30 | extern void ClearBOS(void); /* Clear from cursor to top of screen */ 31 | extern void ClearEOL(void); /* Clear from cursor to end of line */ 32 | extern void ClearBOL(void); /* Clear from cursor to start of line */ 33 | extern void ClearBox(unsigned char, /* Clear a box on the video screen */ 34 | unsigned char, unsigned char, unsigned char, unsigned char); 35 | extern void MapCharSet(int); /* Map a character set */ 36 | extern void SetCharSet(int, unsigned char); /* Set a character set */ 37 | extern void SaveCursor(void); /* Save the cursor description */ 38 | extern void RestoreCursor(void); /* Restore the cursor description */ 39 | extern void SetCursorVisibility(int); /* Set the cursor visibility mode */ 40 | extern void SetBackGround(int); /* Set background video attribute */ 41 | extern void SetColorPalette(unsigned char, /* Set the specific color palette */ 42 | unsigned char*); 43 | extern void ResetColorPalette(void); /* Reset the color palette to default */ 44 | extern void InitTabs(void); /* Initialize the tab settings */ 45 | extern void DoTab(void); /* Perform a tab */ 46 | extern void SetTabStop(void); /* Set a tab stop at cursor position */ 47 | extern void ClearTabStop(void); /* Clear a tab stop at the cursor position */ 48 | extern void ClearAllTabs(void); /* Clear all the defined tab stops */ 49 | extern void SetScreenWidth(int); /* Set the logical width of the screen */ 50 | extern void WriteOneChar(unsigned char, /* Write one character to the screen */ 51 | int, int); 52 | #endif 53 | -------------------------------------------------------------------------------- /include/vttio.h: -------------------------------------------------------------------------------- 1 | #ifndef _VT100_H 2 | #define _VT100_H 3 | 4 | extern void ConOut(unsigned char); /* Put one character to console */ 5 | extern void VTInit(void); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/zconf.h: -------------------------------------------------------------------------------- 1 | /* zconf.h -- configuration of the zlib compression library 2 | * Copyright (C) 1995-1998 Jean-loup Gailly. 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | #ifndef _ZCONF_H 7 | #define _ZCONF_H 8 | 9 | /* 10 | * If you *really* need a unique prefix for all types and library functions, 11 | * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. 12 | */ 13 | #ifdef Z_PREFIX 14 | # define deflateInit_ z_deflateInit_ 15 | # define deflate z_deflate 16 | # define deflateEnd z_deflateEnd 17 | # define inflateInit_ z_inflateInit_ 18 | # define inflate z_inflate 19 | # define inflateEnd z_inflateEnd 20 | # define deflateInit2_ z_deflateInit2_ 21 | # define deflateSetDictionary z_deflateSetDictionary 22 | # define deflateCopy z_deflateCopy 23 | # define deflateReset z_deflateReset 24 | # define deflateParams z_deflateParams 25 | # define inflateInit2_ z_inflateInit2_ 26 | # define inflateSetDictionary z_inflateSetDictionary 27 | # define inflateSync z_inflateSync 28 | # define inflateSyncPoint z_inflateSyncPoint 29 | # define inflateReset z_inflateReset 30 | # define compress z_compress 31 | # define compress2 z_compress2 32 | # define uncompress z_uncompress 33 | # define adler32 z_adler32 34 | # define crc32 z_crc32 35 | # define get_crc_table z_get_crc_table 36 | 37 | # define Byte z_Byte 38 | # define uInt z_uInt 39 | # define uLong z_uLong 40 | # define Bytef z_Bytef 41 | # define charf z_charf 42 | # define intf z_intf 43 | # define uIntf z_uIntf 44 | # define uLongf z_uLongf 45 | # define voidpf z_voidpf 46 | # define voidp z_voidp 47 | #endif 48 | 49 | #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) 50 | # define WIN32 51 | #endif 52 | #if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) 53 | # ifndef __32BIT__ 54 | # define __32BIT__ 55 | # endif 56 | #endif 57 | #if defined(__MSDOS__) && !defined(MSDOS) 58 | # define MSDOS 59 | #endif 60 | 61 | /* 62 | * Compile with -DMAXSEG_64K if the alloc function cannot allocate more 63 | * than 64k bytes at a time (needed on systems with 16-bit int). 64 | */ 65 | #if defined(MSDOS) && !defined(__32BIT__) 66 | # define MAXSEG_64K 67 | #endif 68 | #ifdef MSDOS 69 | # define UNALIGNED_OK 70 | #endif 71 | 72 | #if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) 73 | # define STDC 74 | #endif 75 | #if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) 76 | # ifndef STDC 77 | # define STDC 78 | # endif 79 | #endif 80 | 81 | #ifndef STDC 82 | # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ 83 | # define const 84 | # endif 85 | #endif 86 | 87 | /* Some Mac compilers merge all .h files incorrectly: */ 88 | #if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) 89 | # define NO_DUMMY_DECL 90 | #endif 91 | 92 | /* Old Borland C incorrectly complains about missing returns: */ 93 | #if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) 94 | # define NEED_DUMMY_RETURN 95 | #endif 96 | 97 | 98 | /* Maximum value for memLevel in deflateInit2 */ 99 | #ifndef MAX_MEM_LEVEL 100 | # ifdef MAXSEG_64K 101 | # define MAX_MEM_LEVEL 8 102 | # else 103 | # define MAX_MEM_LEVEL 9 104 | # endif 105 | #endif 106 | 107 | /* Maximum value for windowBits in deflateInit2 and inflateInit2. 108 | * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files 109 | * created by gzip. (Files created by minigzip can still be extracted by 110 | * gzip.) 111 | */ 112 | #ifndef MAX_WBITS 113 | # define MAX_WBITS 15 /* 32K LZ77 window */ 114 | #endif 115 | 116 | /* The memory requirements for deflate are (in bytes): 117 | (1 << (windowBits+2)) + (1 << (memLevel+9)) 118 | that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) 119 | plus a few kilobytes for small objects. For example, if you want to reduce 120 | the default memory requirements from 256K to 128K, compile with 121 | make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" 122 | Of course this will generally degrade compression (there's no free lunch). 123 | 124 | The memory requirements for inflate are (in bytes) 1 << windowBits 125 | that is, 32K for windowBits=15 (default value) plus a few kilobytes 126 | for small objects. 127 | */ 128 | 129 | /* Type declarations */ 130 | 131 | #ifndef OF /* function prototypes */ 132 | # ifdef STDC 133 | # define OF(args) args 134 | # else 135 | # define OF(args) () 136 | # endif 137 | #endif 138 | 139 | /* The following definitions for FAR are needed only for MSDOS mixed 140 | * model programming (small or medium model with some far allocations). 141 | * This was tested only with MSC; for other MSDOS compilers you may have 142 | * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, 143 | * just define FAR to be empty. 144 | */ 145 | #if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) 146 | /* MSC small or medium model */ 147 | # define SMALL_MEDIUM 148 | # ifdef _MSC_VER 149 | # define FAR _far 150 | # else 151 | # define FAR far 152 | # endif 153 | #endif 154 | #if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) 155 | # ifndef __32BIT__ 156 | # define SMALL_MEDIUM 157 | # define FAR _far 158 | # endif 159 | #endif 160 | 161 | /* Compile with -DZLIB_DLL for Windows DLL support */ 162 | #if defined(ZLIB_DLL) 163 | # if defined(_WINDOWS) || defined(WINDOWS) 164 | # ifdef FAR 165 | # undef FAR 166 | # endif 167 | # include 168 | # define ZEXPORT WINAPI 169 | # ifdef WIN32 170 | # define ZEXPORTVA WINAPIV 171 | # else 172 | # define ZEXPORTVA FAR _cdecl _export 173 | # endif 174 | # endif 175 | # if defined (__BORLANDC__) 176 | # if (__BORLANDC__ >= 0x0500) && defined (WIN32) 177 | # include 178 | # define ZEXPORT __declspec(dllexport) WINAPI 179 | # define ZEXPORTRVA __declspec(dllexport) WINAPIV 180 | # else 181 | # if defined (_Windows) && defined (__DLL__) 182 | # define ZEXPORT _export 183 | # define ZEXPORTVA _export 184 | # endif 185 | # endif 186 | # endif 187 | #endif 188 | 189 | #if defined (__BEOS__) 190 | # if defined (ZLIB_DLL) 191 | # define ZEXTERN extern __declspec(dllexport) 192 | # else 193 | # define ZEXTERN extern __declspec(dllimport) 194 | # endif 195 | #endif 196 | 197 | #ifndef ZEXPORT 198 | # define ZEXPORT 199 | #endif 200 | #ifndef ZEXPORTVA 201 | # define ZEXPORTVA 202 | #endif 203 | #ifndef ZEXTERN 204 | # define ZEXTERN extern 205 | #endif 206 | 207 | #ifndef FAR 208 | # define FAR 209 | #endif 210 | 211 | #if !defined(MACOS) && !defined(TARGET_OS_MAC) 212 | typedef unsigned char Byte; /* 8 bits */ 213 | #endif 214 | typedef unsigned int uInt; /* 16 bits or more */ 215 | typedef unsigned long uLong; /* 32 bits or more */ 216 | 217 | #ifdef SMALL_MEDIUM 218 | /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ 219 | # define Bytef Byte FAR 220 | #else 221 | typedef Byte FAR Bytef; 222 | #endif 223 | typedef char FAR charf; 224 | typedef int FAR intf; 225 | typedef uInt FAR uIntf; 226 | typedef uLong FAR uLongf; 227 | 228 | #ifdef STDC 229 | typedef void FAR *voidpf; 230 | typedef void *voidp; 231 | #else 232 | typedef Byte FAR *voidpf; 233 | typedef Byte *voidp; 234 | #endif 235 | 236 | #ifdef HAVE_UNISTD_H 237 | # include /* for off_t */ 238 | # include /* for SEEK_* and off_t */ 239 | # define z_off_t off_t 240 | #endif 241 | #ifndef SEEK_SET 242 | # define SEEK_SET 0 /* Seek from beginning of file. */ 243 | # define SEEK_CUR 1 /* Seek from current position. */ 244 | # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ 245 | #endif 246 | #ifndef z_off_t 247 | # define z_off_t long 248 | #endif 249 | 250 | /* MVS linker does not support external names larger than 8 bytes */ 251 | #if defined(__MVS__) 252 | # pragma map(deflateInit_,"DEIN") 253 | # pragma map(deflateInit2_,"DEIN2") 254 | # pragma map(deflateEnd,"DEEND") 255 | # pragma map(inflateInit_,"ININ") 256 | # pragma map(inflateInit2_,"ININ2") 257 | # pragma map(inflateEnd,"INEND") 258 | # pragma map(inflateSync,"INSY") 259 | # pragma map(inflateSetDictionary,"INSEDI") 260 | # pragma map(inflate_blocks,"INBL") 261 | # pragma map(inflate_blocks_new,"INBLNE") 262 | # pragma map(inflate_blocks_free,"INBLFR") 263 | # pragma map(inflate_blocks_reset,"INBLRE") 264 | # pragma map(inflate_codes_free,"INCOFR") 265 | # pragma map(inflate_codes,"INCO") 266 | # pragma map(inflate_fast,"INFA") 267 | # pragma map(inflate_flush,"INFLU") 268 | # pragma map(inflate_mask,"INMA") 269 | # pragma map(inflate_set_dictionary,"INSEDI2") 270 | # pragma map(inflate_copyright,"INCOPY") 271 | # pragma map(inflate_trees_bits,"INTRBI") 272 | # pragma map(inflate_trees_dynamic,"INTRDY") 273 | # pragma map(inflate_trees_fixed,"INTRFI") 274 | # pragma map(inflate_trees_free,"INTRFR") 275 | #endif 276 | 277 | #endif /* _ZCONF_H */ 278 | -------------------------------------------------------------------------------- /int64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Handling of the int64 and uint64 types. Done in 32-bit integers, 3 | * for (pre-C99) portability. Hopefully once C99 becomes widespread 4 | * we can kiss this lot goodbye... 5 | * 6 | * Taken from the PuTTY source. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "int64.h" 13 | 14 | uint64 uint64_div10(uint64 x, int *remainder) 15 | { 16 | uint64 y; 17 | int rem, r2; 18 | y.hi = x.hi / 10; 19 | y.lo = x.lo / 10; 20 | rem = x.lo % 10; 21 | /* 22 | * Now we have to add in the remainder left over from x.hi. 23 | */ 24 | r2 = x.hi % 10; 25 | y.lo += r2 * 2 * (0x80000000 / 10); 26 | rem += r2 * 2 * (0x80000000 % 10); 27 | y.lo += rem / 10; 28 | rem %= 10; 29 | 30 | if (remainder) 31 | *remainder = rem; 32 | return y; 33 | } 34 | 35 | void uint64_decimal(uint64 x, char *buffer) 36 | { 37 | char buf[20]; 38 | int start = 20; 39 | int d; 40 | 41 | while (x.hi || x.lo) { 42 | x = uint64_div10(x, &d); 43 | assert(start > 0); 44 | buf[--start] = d + '0'; 45 | } 46 | 47 | memcpy(buffer, buf + start, sizeof(buf) - start); 48 | buffer[sizeof(buf) - start] = '\0'; 49 | } 50 | 51 | uint64 uint64_make(unsigned long hi, unsigned long lo) 52 | { 53 | uint64 y; 54 | y.hi = hi; 55 | y.lo = lo; 56 | return y; 57 | } 58 | 59 | uint64 uint64_add(uint64 x, uint64 y) 60 | { 61 | x.lo += y.lo; 62 | x.hi += y.hi + (x.lo < y.lo ? 1 : 0); 63 | return x; 64 | } 65 | 66 | uint64 uint64_add32(uint64 x, unsigned long y) 67 | { 68 | uint64 yy; 69 | yy.hi = 0; 70 | yy.lo = y; 71 | return uint64_add(x, yy); 72 | } 73 | 74 | int uint64_compare(uint64 x, uint64 y) 75 | { 76 | if (x.hi != y.hi) 77 | return x.hi < y.hi ? -1 : +1; 78 | if (x.lo != y.lo) 79 | return x.lo < y.lo ? -1 : +1; 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /keyio.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 1988 Jerry Joplin 2 | * 3 | * Portions copyright (c) 1981, 1988 4 | * Trustees of Columbia University in the City of New York 5 | * 6 | * Permission is granted to any individual or institution 7 | * to use, copy, or redistribute this program and 8 | * documentation as long as it is not sold for profit and 9 | * as long as the Columbia copyright notice is retained. 10 | * 11 | * 12 | * Modified by Nagy Daniel - terminal emulation fixes 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "config.h" 20 | #include "channel.h" 21 | #include "common.h" 22 | #include "common.h" 23 | #include "shell.h" 24 | #include "vidio.h" 25 | #include "keymap.h" 26 | 27 | #define ESC 0x1B /* ASCII ESCape character */ 28 | #define DEL 0x7F /* ASCII DELete character */ 29 | #define BKSP 0x0E08 /* BacKSPace scan code */ 30 | #define F1 0x3B00 /* Function key 1 scan code */ 31 | #define F2 0x3C00 /* Function key 2 scan code */ 32 | #define F3 0x3D00 /* Function key 3 scan code */ 33 | #define F4 0x3E00 /* Function key 4 scan code */ 34 | #define F5 0x3F00 /* Function key 5 scan code */ 35 | #define F6 0x4000 /* Function key 6 scan code */ 36 | #define F7 0x4100 /* Function key 7 scan code */ 37 | #define F8 0x4200 /* Function key 8 scan code */ 38 | #define F9 0x4300 /* Function key 9 scan code */ 39 | #define F10 0x4400 /* Function key 10 scan code */ 40 | #define F11 0x8500 /* Function key 11 scan code */ 41 | #define F12 0x8600 /* Function key 12 scan code */ 42 | #define UPG 0x48E0 /* Gray Up Arrow scan code */ 43 | #define UPW 0x4800 /* White Up Arrow scan code */ 44 | #define DOWNG 0x50E0 /* Gray Down Arrow scan code */ 45 | #define DOWNW 0x5000 /* White Down Arrow scan code */ 46 | #define LEFTG 0x4BE0 /* Gray Left Arrow scan code */ 47 | #define LEFTW 0x4B00 /* White Left Arrow scan code */ 48 | #define RIGHTG 0x4DE0 /* Gray Right Arrow scan code */ 49 | #define RIGHTW 0x4D00 /* White Right Arrow scan code */ 50 | #define K7 0x4737 /* Keyboard Numeric 7 scan code */ 51 | #define K8 0x4838 /* Keyboard Numeric 8 scan code */ 52 | #define K9 0x4939 /* Keyboard Numeric 9 scan code */ 53 | #define KDASH 0x372A /* Keyboard Numeric Asterisk scan code */ 54 | #define K4 0x4B34 /* Keyboard Numeric 4 scan code */ 55 | #define K5 0x4C35 /* Keyboard Numeric 5 scan code */ 56 | #define K6 0x4D36 /* Keyboard Numeric 6 scan code */ 57 | #define KMINUS 0x4A2D /* Keyboard Numeric Dash(minus) scan code */ 58 | #define K1 0x4F31 /* Keyboard Numeric 1 scan code */ 59 | #define K2 0x5032 /* Keyboard Numeric 2 scan code */ 60 | #define K3 0x5133 /* Keyboard Numeric 3 scan code */ 61 | #define KPLUS 0x4E2B /* Keyboard Numeric + (plus) scan code */ 62 | #define K0 0x5230 /* Keyboard Numeric 0 scan code */ 63 | #define KDOT 0x532E /* Keyboard Numeric Period scan code */ 64 | #define INSERTG 0x52E0 /* Gray insert */ 65 | #define INSERTW 0x5200 /* White insert */ 66 | #define DELETEG 0x53E0 /* Gray delete */ 67 | #define DELETEW 0x5300 /* White delete */ 68 | #define HOMEG 0x47E0 /* Gray home */ 69 | #define HOMEW 0x4700 /* White home */ 70 | #define ENDG 0x4FE0 /* Gray end */ 71 | #define ENDW 0x4F00 /* White end */ 72 | #define PGUPG 0x49E0 /* Gray page up */ 73 | #define PGUPW 0x4900 /* White page up */ 74 | #define PGDOWNG 0x51E0 /* Gray page down */ 75 | #define PGDOWNW 0x5100 /* White page down */ 76 | #define ALTX 0x2D00 /* ALT-X: terminate session */ 77 | #define ALTE 0x1200 /* ALT-E: DOS shell */ 78 | 79 | /*****************************************************************************/ 80 | /*external function prototypes */ 81 | 82 | extern SendFuncPtr SendPacket; 83 | 84 | /*****************************************************************************/ 85 | /* Local Static data */ 86 | 87 | static char cursorkey = '['; /* Sequence character in cursor key */ 88 | static unsigned char applkeypad = 0; /* Current state of keypad */ 89 | 90 | /*****************************************************************************/ 91 | /*****************************************************************************/ 92 | 93 | 94 | /* 95 | * Send a character 96 | */ 97 | static void ttoc(char c) 98 | { 99 | SendPacket(&c, 1); 100 | } 101 | 102 | 103 | /* 104 | * Send two characters after an ESC 105 | */ 106 | static void ttoe2c(char c1, char c2) 107 | { 108 | char buff[3]; 109 | 110 | buff[0] = ESC; 111 | buff[1] = c1; 112 | buff[2] = c2; 113 | SendPacket(buff, 3); 114 | } 115 | 116 | 117 | /* 118 | * Send two characters after ANSI 119 | */ 120 | static void ttoea2c(char c1, char c2) 121 | { 122 | char buff[4]; 123 | 124 | buff[0] = ESC; 125 | buff[1] = 0x5b; 126 | buff[2] = c1; 127 | buff[3] = c2; 128 | SendPacket(buff, 4); 129 | } 130 | 131 | 132 | /* 133 | * Send three characters after ANSI 134 | */ 135 | static void ttoea3c(char c1, char c2, char c3) 136 | { 137 | char buff[5]; 138 | 139 | buff[0] = ESC; 140 | buff[1] = 0x5b; 141 | buff[2] = c1; 142 | buff[3] = c2; 143 | buff[4] = c3; 144 | SendPacket(buff, 5); 145 | } 146 | 147 | 148 | /* G E T K E Y -- Return a keyboard scan code */ 149 | 150 | static unsigned int GetKey(void) 151 | { 152 | return(_bios_keybrd(_NKEYBRD_READ)); /* check for waiting keystrokes */ 153 | } 154 | 155 | 156 | /* T R A N S N U M K E Y -- Try and translate key from the Numeric Keypad */ 157 | 158 | static int TransNumKey(register unsigned key) 159 | { 160 | 161 | if (applkeypad != 0) /* If keypad is not in NUMERIC mode */ 162 | return (0); /* then no translation here possible */ 163 | 164 | switch (key) { 165 | case K7: /* Numeric 7 pressed */ 166 | ttoc('7'); 167 | break; 168 | case K8: /* Numeric 8 pressed */ 169 | ttoc('8'); 170 | break; 171 | case K9: /* Numeric 9 pressed */ 172 | ttoc('9'); 173 | break; 174 | case KDASH: /* Numeric Asterisk pressed */ 175 | ttoc('*'); 176 | break; 177 | case K4: /* Numeric 4 pressed */ 178 | ttoc('4'); 179 | break; 180 | case K5: /* Numeric 5 pressed */ 181 | ttoc('5'); 182 | break; 183 | case K6: /* Numeric 6 pressed */ 184 | ttoc('6'); 185 | break; 186 | case KMINUS: /* Numeric Minus pressed */ 187 | ttoc('-'); 188 | break; 189 | case K1: /* Numeric 1 pressed */ 190 | ttoc('1'); 191 | break; 192 | case K2: /* Numeric 2 pressed */ 193 | ttoc('2'); 194 | break; 195 | case K3: /* Numeric 3 pressed */ 196 | ttoc('3'); 197 | break; 198 | case K0: /* Numeric 0 pressed */ 199 | ttoc('0'); 200 | break; 201 | case KDOT: /* Numeric Period pressed */ 202 | ttoc('.'); 203 | break; 204 | case KPLUS: /* Numeric Plus pressed */ 205 | ttoc('+'); 206 | break; 207 | default: 208 | return (0); /* No translation */ 209 | } 210 | return (1); 211 | } 212 | 213 | 214 | /* T R A N S A P P L K E Y -- Try and translate key from Application Keypad*/ 215 | 216 | static int TransApplKey(register unsigned key) 217 | { 218 | 219 | if (applkeypad != 1) /* If keypad is not APPLICATION mode */ 220 | return (0); /* then no translation here possible */ 221 | 222 | switch (key) { 223 | case K0: /* Application key 0 pressed */ 224 | ttoe2c('O', 'p'); 225 | break; 226 | case K1: /* Application key 1 pressed */ 227 | ttoe2c('O', 'q'); 228 | break; 229 | case K2: /* Application key 2 pressed */ 230 | ttoe2c('O', 'r'); 231 | break; 232 | case K3: /* Application key 3 pressed */ 233 | ttoe2c('O', 's'); 234 | break; 235 | case K4: /* Application key 4 pressed */ 236 | ttoe2c('O', 't'); 237 | break; 238 | case K5: /* Application key 5 pressed */ 239 | ttoe2c('O', 'u'); 240 | break; 241 | case K6: /* Application key 6 pressed */ 242 | ttoe2c('O', 'v'); 243 | break; 244 | case K7: /* Application key 7 pressed */ 245 | ttoe2c('O', 'w'); 246 | break; 247 | case K8: /* Application key 8 pressed */ 248 | ttoe2c('O', 'x'); 249 | break; 250 | case K9: /* Application key 9 pressed */ 251 | ttoe2c('O', 'y'); 252 | break; 253 | case KDASH: /* Application key Asterisk pressed */ 254 | ttoe2c('O', 'm'); 255 | break; 256 | case KMINUS: /* Application key Minus pressed */ 257 | ttoe2c('O', 'l'); 258 | break; 259 | case KDOT: /* Application key Dot pressed */ 260 | ttoe2c('O', 'n'); 261 | break; 262 | case KPLUS: /* Application key Plus pressed */ 263 | ttoe2c('O', 'M'); 264 | break; 265 | default: 266 | return (0); /* No translation */ 267 | } 268 | return (1); 269 | } 270 | 271 | 272 | /* T R A N S K E Y -- translate a scancode into a keystroke sequence */ 273 | 274 | static void TransKey(unsigned key) 275 | { 276 | char *value; 277 | char n; 278 | 279 | n = _bios_keybrd(_KEYBRD_SHIFTSTATUS) & 3; /* shift state */ 280 | if(n){ /* examine scrollback keys first */ 281 | if(key == PGUPG || key == PGUPW){ 282 | SbkBack(); 283 | return; 284 | } else if(key == PGDOWNG || key == PGDOWNW){ 285 | SbkForward(); 286 | return; 287 | } 288 | } 289 | 290 | SbkSetPage(-1); 291 | 292 | if ((value = keymap_value(key)) != NULL) { 293 | SendPacket(value, strlen(value)); 294 | return; 295 | } 296 | switch (key) { /* Evaluate this keyboard scan code */ 297 | 298 | case BKSP: /* Backspace pressed */ 299 | ttoc(DEL); 300 | break; 301 | 302 | case F1: /* Function key 1 pressed */ 303 | ttoea3c('1','1',0x7e); 304 | break; 305 | 306 | case F2: /* Function key 2 pressed */ 307 | ttoea3c('1','2',0x7e); 308 | break; 309 | 310 | case F3: /* Function key 3 pressed */ 311 | ttoea3c('1','3',0x7e); 312 | break; 313 | 314 | case F4: /* Function key 4 pressed */ 315 | ttoea3c('1','4',0x7e); 316 | break; 317 | 318 | case F5: /* Function key 5 pressed */ 319 | ttoea3c('1','5',0x7e); 320 | break; 321 | 322 | case F6: /* Function key 6 pressed */ 323 | ttoea3c('1','7',0x7e); 324 | break; 325 | 326 | case F7: /* Function key 7 pressed */ 327 | ttoea3c('1','8',0x7e); 328 | break; 329 | 330 | case F8: /* Function key 8 pressed */ 331 | ttoea3c('1','9',0x7e); 332 | break; 333 | 334 | case F9: /* Function key 9 pressed */ 335 | ttoea3c('2','0',0x7e); 336 | break; 337 | 338 | case F10: /* Function key 10 pressed */ 339 | ttoea3c('2','1',0x7e); 340 | break; 341 | 342 | case F11: /* Function key 11 pressed */ 343 | ttoea3c('2','3',0x7e); 344 | break; 345 | 346 | case F12: /* Function key 12 pressed */ 347 | ttoea3c('2','4',0x7e); 348 | break; 349 | 350 | case UPG: /* Up Arrow pressed */ 351 | case UPW: 352 | ttoe2c(cursorkey, 'A'); 353 | break; 354 | 355 | case DOWNG: /* Down Arrow pressed */ 356 | case DOWNW: 357 | ttoe2c(cursorkey, 'B'); 358 | break; 359 | 360 | case RIGHTG: /* Right Arrow pressed */ 361 | case RIGHTW: 362 | ttoe2c(cursorkey, 'C'); 363 | break; 364 | 365 | case LEFTG: /* Left Arrow pressed */ 366 | case LEFTW: 367 | ttoe2c(cursorkey, 'D'); 368 | break; 369 | 370 | case INSERTG: 371 | case INSERTW: 372 | ttoea2c('2', 0x7E); 373 | break; 374 | 375 | case DELETEG: 376 | case DELETEW: 377 | ttoea2c('3', 0x7E); 378 | break; 379 | 380 | case HOMEG: 381 | case HOMEW: 382 | ttoe2c('O', 'H'); 383 | break; 384 | 385 | case ENDG: 386 | case ENDW: 387 | ttoe2c('O', 'F'); 388 | break; 389 | 390 | case PGUPG: 391 | case PGUPW: 392 | ttoea2c('5', 0x7E); 393 | break; 394 | 395 | case PGDOWNG: 396 | case PGDOWNW: 397 | ttoea2c('6', 0x7E); 398 | break; 399 | 400 | case ALTX: 401 | fatal("Terminating session"); 402 | 403 | case ALTE: /* DOS shell */ 404 | Shell(); 405 | break; 406 | 407 | default: /* No translation yet, check numeric pad */ 408 | if ((TransNumKey(key) == 0) && (TransApplKey(key) == 0)) 409 | ttoc((char) key); /* Still no translation, transmit char */ 410 | break; 411 | } 412 | } 413 | 414 | 415 | /* C O N C H K -- Check if any key strokes are waiting */ 416 | 417 | int ConChk(void) 418 | { 419 | return(_bios_keybrd(_NKEYBRD_READY)); 420 | } 421 | 422 | 423 | /* D O K E Y -- Retrieve and interpret a keystroke */ 424 | 425 | void DoKey(void) 426 | { 427 | unsigned scancode; 428 | 429 | scancode = GetKey(); /* Get a keystroke, waits if none ready */ 430 | TransKey(scancode); 431 | } 432 | 433 | 434 | /* S E T K E Y P A D -- Set the keypad translation */ 435 | 436 | void SetKeyPad(int mode) 437 | { 438 | applkeypad = mode ? 1 : 0; /* keypad = APPLICATION/NUMERIC */ 439 | } 440 | 441 | /* S E T C U R S O R K E Y -- Set the cursior key mode */ 442 | 443 | void SetCursorKey(mode) 444 | { 445 | /* This establishes the second character */ 446 | /* of the cursor keys escape sequence */ 447 | cursorkey = mode ? 'O' : '['; 448 | } 449 | -------------------------------------------------------------------------------- /keymap.c: -------------------------------------------------------------------------------- 1 | /* keymap.c Copyright (c) 2001-2002 Shane Wegner 2 | * 3 | * $Date: 2005/12/30 16:26:40 $ 4 | * $Revision: 1.3 $ 5 | * 6 | * This module provides keymap support. 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License 10 | * as published by the Free Software Foundation; either version 2 11 | * of the License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Library General Public 19 | * License along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "common.h" 29 | #if defined (MEMWATCH) 30 | #include "memwatch.h" 31 | #endif 32 | 33 | struct keymap { 34 | unsigned int scancode; 35 | char *value; 36 | struct keymap *next; 37 | }; 38 | 39 | static struct keymap *keymaps = NULL; 40 | 41 | char *keymap_value(unsigned int scancode) 42 | { 43 | struct keymap *k; 44 | 45 | for (k = keymaps; k != NULL; k = k->next) 46 | if (k->scancode == scancode) 47 | return k->value; 48 | return NULL; 49 | } 50 | 51 | 52 | void keymap_uninit(void) 53 | { 54 | struct keymap *k, *p; 55 | 56 | for (k = keymaps; k != NULL; ) { 57 | p = k; 58 | k = k->next; 59 | free(p->value); 60 | free(p); 61 | } 62 | } 63 | 64 | 65 | static void keymap_add(unsigned int scancode, const char *value) 66 | { 67 | struct keymap *k, *p = NULL; 68 | unsigned char *v; 69 | 70 | if((v = (unsigned char*)malloc(strlen(value) + 1)) == NULL) 71 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 72 | strcpy(v, value); 73 | for (k = keymaps; k != NULL; k = k->next) { 74 | if (k->scancode == scancode) { 75 | /* Just replace the current value and return */ 76 | free(k->value); 77 | k->value = v; 78 | return; 79 | } /* if */ 80 | p = k; 81 | } /* for */ 82 | 83 | if((k = (struct keymap *)malloc(sizeof(struct keymap))) == NULL) 84 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 85 | 86 | k->scancode = scancode; 87 | k->value = v; 88 | k->next = NULL; 89 | if (p != NULL) 90 | p->next = k; 91 | else 92 | keymaps = k; 93 | 94 | } 95 | 96 | void keymap_init(const char *filename) 97 | { 98 | FILE *kf; 99 | char *line, *newvalue; 100 | char *cmd, *key, *value, *valptr, *endptr; 101 | unsigned int scancode; 102 | int i; 103 | 104 | if((kf = fopen(filename, "r")) == NULL) 105 | fatal("Cannot open keymap file"); 106 | 107 | if((line = (char *)malloc(1024)) == NULL) 108 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 109 | if((newvalue = (char *)malloc(1024)) == NULL) 110 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 111 | 112 | while(fgets(line, 1024, kf) != NULL) { 113 | if (!*line) 114 | continue; 115 | while (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r') 116 | line[strlen(line) - 1] = 0; 117 | while (*line == ' ' || *line == '\t') 118 | memmove(line, line+1, strlen(line)); 119 | if (!*line || *line == '#') 120 | continue; 121 | 122 | /* Now to the real work */ 123 | if ((cmd = strtok(line, " ")) == NULL) 124 | continue; 125 | if (!strcmp(cmd, "mapkey")){ 126 | if ((key = strtok(NULL, " ")) == NULL) 127 | continue; 128 | if ((value = strtok(NULL, "\00")) == NULL) 129 | continue; 130 | scancode = strtoul(key, NULL, 0); 131 | if (!scancode) 132 | continue; 133 | memset(newvalue, 0, 1024); 134 | i = 0; 135 | for (valptr = value; *valptr; valptr++) { 136 | if (*valptr == '\\') { 137 | valptr++; 138 | if (!*valptr) 139 | break; 140 | switch(*valptr) { 141 | case '0': 142 | case '1': 143 | case '2': 144 | case '3': 145 | case '4': 146 | case '5': 147 | case '6': 148 | case '7': 149 | case '8': 150 | case '9': /* octal digit */ 151 | newvalue[i++] = strtol(valptr, &endptr, 8); 152 | if (endptr != valptr) 153 | valptr = endptr - 1; 154 | break; 155 | 156 | case 'a': /* bell */ 157 | newvalue[i++] = '\a'; 158 | break; 159 | 160 | case 'e': /* escape */ 161 | case 'E': 162 | newvalue[i++] = 0x1b; 163 | break; 164 | 165 | case 'n': /* newline */ 166 | newvalue[i++] = '\n'; 167 | break; 168 | 169 | case 't': /* tab */ 170 | newvalue[i++] = '\t'; 171 | break; 172 | 173 | default: 174 | newvalue[i++] = *valptr; 175 | } /* switch */ 176 | } else 177 | newvalue[i++] = *valptr; 178 | } /* for */ 179 | keymap_add(scancode, newvalue); 180 | } /* if mapkey */ 181 | } /* while fgets */ 182 | 183 | free(line); 184 | free(newvalue); 185 | 186 | fclose(kf); 187 | } 188 | -------------------------------------------------------------------------------- /linux.kbd: -------------------------------------------------------------------------------- 1 | # linux.kbd -- sshdos keymap for linux terminals. 2 | # Written by Nagy Daniel 2002-02-11. 3 | # Based on the linux terminfo database entry. 4 | # Contains only differences to the original xterm keymap 5 | 6 | # key_up 7 | mapkey 0x48e0 \E[A 8 | # key_down 9 | mapkey 0x50e0 \E[B 10 | # key_right 11 | mapkey 0x4de0 \E[C 12 | # key_left 13 | mapkey 0x4be0 \E[D 14 | # key_home 15 | mapkey 0x47e0 \E[1~ 16 | # key_end 17 | mapkey 0x4fe0 \E[4~ 18 | # key_f1 19 | mapkey 0x3b00 \E[[A 20 | # key_f2 21 | mapkey 0x3c00 \E[[B 22 | # key_f3 23 | mapkey 0x3d00 \E[[C 24 | # key_f4 25 | mapkey 0x3e00 \E[[D 26 | # key_f5 27 | mapkey 0x3f00 \E[[E 28 | -------------------------------------------------------------------------------- /negotiat.c: -------------------------------------------------------------------------------- 1 | /* negotiat.c Copyright (c) 2000-2005 Nagy Daniel 2 | * 3 | * $Date: 2005/12/30 16:26:40 $ 4 | * $Revision: 1.5 $ 5 | * 6 | * This module is the SSH negotiation part: 7 | * - open TCP connection 8 | * - protocol version check 9 | * - initiate key exchange (transport layer) 10 | * - initiate user authorization (authentication layer) 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation; either version 2 15 | * of the License, or (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU Library General Public 23 | * License along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "tcp.h" 32 | #include "auth.h" 33 | #include "config.h" 34 | #include "common.h" 35 | #include "channel.h" 36 | #include "sshsha.h" 37 | #include "ssh.h" 38 | #include "transprt.h" 39 | #include "version.h" 40 | 41 | /* external functions, data */ 42 | extern Config GlobalConfig; /* configuration variables */ 43 | extern unsigned short Configuration; /* configuration bitfields */ 44 | extern char *RemoteClosed; 45 | extern char *ConnectionClosed; 46 | 47 | /* global variables */ 48 | SHA256_State exhash256base; 49 | 50 | /* 51 | * SSH version string exchange: get server's SSH protocol 52 | * version, examine it, and send ours if it seems that we 53 | * can communicate 54 | */ 55 | static short SSH_Exchange_Identification(void) 56 | { 57 | char localstr[256], remotestr[256]; 58 | unsigned short remote_major, remote_minor; 59 | int i; 60 | 61 | if(Configuration & VERBOSE_MODE) 62 | puts("Identification Exchange"); 63 | 64 | /* Read other side's version identification. */ 65 | do{ 66 | if(!(i = sock_gets(&GlobalConfig.s, remotestr, sizeof(remotestr)))){ 67 | fatal("Cannot read remote identification string"); 68 | } 69 | } while(strncmp(remotestr, "SSH-", 4)); /* ignore other lines */ 70 | 71 | if(sscanf(remotestr, "SSH-%hu.%hu-", &remote_major, &remote_minor) != 2){ 72 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_ERROR, "Bad remote protocol version identification"); 73 | return(1); 74 | } 75 | 76 | remotestr[i] = 0; 77 | remotestr[strcspn(remotestr, "\r\n")] = 0; /* cut \r\n if exists */ 78 | 79 | if(Configuration & VERBOSE_MODE) 80 | printf("Remote version: %s\r\n",remotestr); 81 | 82 | sprintf(localstr, "SSH-%d.%d-SSHDOS_%s\r\n", PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); 83 | if(Configuration & VERBOSE_MODE) 84 | printf("Local version: %s", localstr); 85 | 86 | if(remote_major < 2 && remote_minor != 99){ 87 | SSH_Disconnect(SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, "Unsupported remote protocol version"); 88 | return(1); 89 | } 90 | 91 | if(sock_write(&GlobalConfig.s, localstr, strlen(localstr)) != strlen(localstr)) 92 | fatal("Socket write error. File: %s, line: %u", __FILE__, __LINE__); 93 | 94 | /* 95 | * We must hash the version strings for the Diffie-Hellman 96 | * key exchange 97 | */ 98 | 99 | SHA256_Init(&exhash256base); 100 | sha256_string(&exhash256base, localstr, strcspn(localstr, "\r\n")); 101 | sha256_string(&exhash256base, remotestr, strlen(remotestr)); 102 | 103 | return(0); 104 | } 105 | 106 | /* 107 | * Run SSH negotiation process 108 | */ 109 | short SSH_Connect(char *username, char *password, char *keyfile) 110 | { 111 | int status; 112 | 113 | /* Initialize important variables */ 114 | SSH2_init(); 115 | 116 | /* Wait for host version packet */ 117 | sock_wait_input(&GlobalConfig.s, sock_delay, NULL, &status); 118 | 119 | /* Version string exchange and verification */ 120 | if(SSH_Exchange_Identification()) 121 | return(1); 122 | 123 | /* 124 | * Now we wait for host key exchange. This will also do 125 | * our key exchange, done by the transport layer 126 | */ 127 | if(Configuration & VERBOSE_MODE) 128 | puts("Receiving host's key exchange packet"); 129 | if(SSH_pkt_read(SSH_MSG_KEXINIT)) 130 | return(1); 131 | 132 | /* Now we encrypt, hash and maybe compress */ 133 | Configuration |= CIPHER_ENABLED; 134 | if((Configuration & COMPRESSION_REQUESTED)) 135 | Request_Compression(6); 136 | 137 | /* 138 | * Request authorization and wait a response to it. 139 | */ 140 | SSH_pkt_init(SSH_MSG_SERVICE_REQUEST); 141 | SSH_putstring("ssh-userauth"); 142 | if(Configuration & VERBOSE_MODE) 143 | puts("Requesting authorization"); 144 | SSH_pkt_send(); 145 | if(SSH_pkt_read(SSH_MSG_SERVICE_ACCEPT)) 146 | return(1); 147 | 148 | /* 149 | * Try public key authentication first 150 | * Then keyboard-interactive 151 | * Then password authentication 152 | */ 153 | if(SSH2_Auth_Pubkey(username, keyfile)) 154 | if(SSH2_Auth_KbdInt(username, password)) 155 | if(SSH2_Auth_Password(username, password)) 156 | return(1); 157 | 158 | /* Open a channel */ 159 | SSH2_Channel_Open(); 160 | 161 | return(0); 162 | 163 | sock_err: 164 | switch(status){ 165 | case 1: 166 | puts(ConnectionClosed); 167 | break; 168 | 169 | case -1: 170 | puts(RemoteClosed); 171 | break; 172 | } 173 | return(1); 174 | } 175 | -------------------------------------------------------------------------------- /proxy.c: -------------------------------------------------------------------------------- 1 | /* proxy.c Copyright (c) 2000-2003 Nagy Daniel 2 | * 3 | * $Date: 2005/12/30 16:26:40 $ 4 | * $Revision: 1.2 $ 5 | * 6 | * This module is the proxy relaying part 7 | * 8 | * 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; either version 2 13 | * of the License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Library General Public 21 | * License along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 23 | */ 24 | 25 | 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "tcp.h" 32 | #include "config.h" 33 | #include "common.h" 34 | #include "proxy.h" 35 | #include "macros.h" 36 | #if defined (MEMWATCH) 37 | #include "memwatch.h" 38 | #endif 39 | 40 | extern Config GlobalConfig; 41 | 42 | /* 43 | * SOCKS5 user/pass authentication 44 | */ 45 | static short socks5_userauth(char *proxyuser, char *proxypass) 46 | { 47 | char buf[64]; 48 | short n; 49 | 50 | /* construct auth packet */ 51 | n = strlen(proxyuser); 52 | buf[0] = 0x01; 53 | buf[1] = n; 54 | memcpy(buf + 2, proxyuser, n); 55 | n += 2; 56 | buf[n++] = strlen(proxypass); 57 | memcpy(buf + n, proxypass, strlen(proxypass)); 58 | n += strlen(proxypass); 59 | if(sock_write(&GlobalConfig.s, buf, n) != n) /* send it */ 60 | fatal("Socket write error. File: %s, line: %u", __FILE__, __LINE__); 61 | 62 | /* get and parse response */ 63 | if(sock_read(&GlobalConfig.s, buf, 2) != 2) 64 | fatal("Socket read error. File: %s, line: %u", __FILE__, __LINE__); 65 | 66 | if(buf[0] != 0x01 && buf[1] != 0x00){ 67 | puts("socks5_userauth: bad version or user/pass"); 68 | return(-1); 69 | } 70 | 71 | return(0); 72 | } 73 | 74 | 75 | /* 76 | * SOCKS5 connect 77 | */ 78 | short socks5_connect(char *remotehost, unsigned short remoteport, 79 | char *proxyuser, char *proxypass) 80 | { 81 | short n; 82 | char buf[64]; 83 | char *errors[] = { NULL, 84 | "general SOCKS server failure\n", 85 | "connection not allowed by ruleset\n", 86 | "Network unreachable\n", 87 | "Host unreachable\n", 88 | "Connection refused\n", 89 | "TTL expired\n", 90 | "Command not supported\n", 91 | "Address type not supported\n", 92 | "Invalid address\n"}; 93 | 94 | buf[0] = 0x05; 95 | if(proxyuser){ /* we have user/pass */ 96 | buf[1] = 0x02; /* two auth methods */ 97 | buf[2] = 0x00; /* try no auth */ 98 | buf[3] = 0x02; /* try user/pass auth */ 99 | n = 4; 100 | } else { /* only no auth method */ 101 | buf[1] = 0x01; 102 | buf[2] = 0x00; 103 | n = 3; 104 | } 105 | if(sock_write(&GlobalConfig.s, buf, n) != n) /* send auth req */ 106 | fatal("Socket write error. File: %s, line: %u", __FILE__, __LINE__); 107 | 108 | /* get and parse auth method response */ 109 | if(sock_read(&GlobalConfig.s, buf, 2) != 2) 110 | fatal("Socket read error. File: %s, line: %u", __FILE__, __LINE__); 111 | if(buf[0] != 0x05){ 112 | puts("socks5: bad auth response version"); 113 | return(-1); 114 | } 115 | switch(buf[1]){ 116 | case 0: /* no auth */ 117 | break; 118 | 119 | case 2: /* username/passwd */ 120 | if(proxyuser){ /* we have user/pass */ 121 | if(socks5_userauth(proxyuser, proxypass)) 122 | return(-1); 123 | else 124 | break; 125 | } else { 126 | puts("socks5: no user/pass specified"); 127 | return(-1); 128 | } 129 | 130 | default: 131 | puts("socks5: unsupported auth"); 132 | return(-1); 133 | } /* switch */ 134 | 135 | /* auth is done, request connection to remote host */ 136 | buf[0] = 0x05; 137 | buf[1] = 0x01; 138 | buf[2] = 0x00; 139 | buf[3] = 0x03; /* ascii address type, not IP */ 140 | n = strlen(remotehost); 141 | buf[4] = n; 142 | memcpy(buf + 5, remotehost, n); 143 | n += 5; 144 | PUT_16BIT_MSB_FIRST(buf + n, remoteport); 145 | n += 2; 146 | if(sock_write(&GlobalConfig.s, buf, n) != n) /* send req */ 147 | fatal("Socket write error. File: %s, line: %u", __FILE__, __LINE__); 148 | 149 | /* get and parse response */ 150 | if(sock_read(&GlobalConfig.s, buf, 5) != 5) /* this is enough to determine full length */ 151 | fatal("Socket read error. File: %s, line: %u", __FILE__, __LINE__); 152 | if(buf[0] != 0x05){ 153 | puts("socks5: bad connection response version"); 154 | return(-1); 155 | } 156 | if(buf[1]){ 157 | printf("SOCKS5 error: "); 158 | if(buf[1] > 0x0A) 159 | printf("unknown error"); 160 | else 161 | printf(errors[(short)buf[1]]); 162 | return(-1); 163 | } /* if */ 164 | 165 | switch (buf[3]) { 166 | case 1: /* IP address */ 167 | if(sock_read(&GlobalConfig.s, buf, 5) != 5) /* read rest */ 168 | fatal("Socket read error. File: %s, line: %u", __FILE__, __LINE__); 169 | break; 170 | 171 | case 3: /* domainname */ 172 | if(sock_read(&GlobalConfig.s, buf, buf[4] + 2) != buf[4] + 2) /* read rest */ 173 | fatal("Socket read error. File: %s, line: %u", __FILE__, __LINE__); 174 | break; 175 | 176 | default: 177 | fatal("Bad SOCKS5 connection response"); 178 | } 179 | return(0); 180 | } 181 | 182 | /*------------------------------- HTTP part -------------------------------*/ 183 | 184 | 185 | /* 186 | * Base64 encoding 187 | */ 188 | static char *b64_string(const char *str) 189 | { 190 | const char *base64_table = 191 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 192 | 193 | static char *buf; 194 | unsigned char *src; 195 | char *dst; 196 | int bits, data, src_len, dst_len; 197 | 198 | /* make base64 string */ 199 | src_len = strlen(str); 200 | dst_len = (src_len+2)/3*4; 201 | if((buf = (char *)malloc(dst_len+1)) == NULL) 202 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 203 | bits = data = 0; 204 | src = (unsigned char *)str; 205 | dst = (unsigned char *)buf; 206 | while ( dst_len-- ) { 207 | if ( bits < 6 ) { 208 | data = (data << 8) | *src; 209 | bits += 8; 210 | if ( *src != 0 ) 211 | src++; 212 | } 213 | *dst++ = base64_table[0x3F & (data >> (bits-6))]; 214 | bits -= 6; 215 | } 216 | *dst = '\0'; 217 | /* fix-up tail padding */ 218 | switch ( src_len%3 ) { 219 | case 1: 220 | *--dst = '='; 221 | case 2: 222 | *--dst = '='; 223 | } 224 | return buf; 225 | } 226 | 227 | 228 | /* 229 | * HTTP basic authentication 230 | */ 231 | static short http_auth(char *proxyuser, char *proxypass) 232 | { 233 | char *p, *c; 234 | short len, ret; 235 | 236 | len = strlen(proxyuser) + strlen(proxypass) + 1; 237 | if((p = (char *)malloc(len + 1)) == NULL) 238 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 239 | sprintf(p, "%s:%s", proxyuser, proxypass); 240 | c = b64_string(p); 241 | ret = sock_printf(&GlobalConfig.s, "Proxy-Authorization: Basic %s\r\n", c); 242 | free(c); 243 | free(p); 244 | 245 | return ret; 246 | } 247 | 248 | 249 | 250 | /* 251 | * HTTP connect 252 | */ 253 | short http_connect(char *remotehost, unsigned short remoteport, 254 | char *proxyuser, char *proxypass) 255 | { 256 | char buf[1024]; 257 | short result, n; 258 | 259 | if(sock_printf(&GlobalConfig.s,"CONNECT %s:%d HTTP/1.0\r\n", remotehost, remoteport) < 0) 260 | return -1; 261 | if(proxyuser) 262 | if(http_auth(proxyuser, proxypass) < 0) 263 | return -1; 264 | if(sock_puts(&GlobalConfig.s, "\r\n") < 0) 265 | return -1; 266 | 267 | /* get response */ 268 | n = -1; 269 | do{ 270 | n++; 271 | buf[n] = sock_getc(&GlobalConfig.s); 272 | } while(buf[n] != '\n'); 273 | /* check status */ 274 | result = atoi(strchr(buf,' ')); 275 | if(result != 200) 276 | return -1; 277 | 278 | /* skip to end of response header */ 279 | do{ 280 | n = -1; 281 | do{ 282 | n++; 283 | buf[n] = sock_getc(&GlobalConfig.s); 284 | } while(buf[n] != '\n'); 285 | }while(buf[1] != '\n'); 286 | 287 | return 0; 288 | } 289 | -------------------------------------------------------------------------------- /scp2d386.lnk: -------------------------------------------------------------------------------- 1 | System causeway 2 | Name scp2d386.exe 3 | Debug all 4 | Option map 5 | File scpdos.obj 6 | Library crypto.lib,misc.lib,ssh.lib,vt100.lib,zlib_f.lib,wattcpwf.lib 7 | -------------------------------------------------------------------------------- /scp2dos.lnk: -------------------------------------------------------------------------------- 1 | System dos 2 | Name scp2dos.exe 3 | Debug all 4 | Option map 5 | File scpdos.obj 6 | Library crypto.lib,misc.lib,ssh.lib,vt100.lib,zlib_l.lib,wattcpwl.lib 7 | -------------------------------------------------------------------------------- /sftpd386.lnk: -------------------------------------------------------------------------------- 1 | System causeway 2 | Name sftpd386.exe 3 | Debug all 4 | Option map 5 | File sftpdos.obj,sftp.obj 6 | Library crypto.lib,misc.lib,ssh.lib,vt100.lib,zlib_f.lib,wattcpwf.lib 7 | -------------------------------------------------------------------------------- /sftpdos.lnk: -------------------------------------------------------------------------------- 1 | System dos 2 | Name sftpdos.exe 3 | Debug all 4 | Option map 5 | File sftpdos.obj,sftp.obj 6 | Library crypto.lib,misc.lib,ssh.lib,vt100.lib,zlib_l.lib,wattcpwl.lib 7 | Option Stack=4k 8 | -------------------------------------------------------------------------------- /shell.c: -------------------------------------------------------------------------------- 1 | /* shell.c Copyright (c) 2000-2003 Nagy Daniel 2 | * 3 | * $Date: 2005/12/30 16:26:41 $ 4 | * $Revision: 1.4 $ 5 | * 6 | * This module spawns a DOS shell 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License 10 | * as published by the Free Software Foundation; either version 2 11 | * of the License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Library General Public 19 | * License along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "vidio.h" 30 | 31 | 32 | /* 33 | * Spawn a DOS shell 34 | */ 35 | void Shell(void) 36 | { 37 | char *comspec; 38 | char olddir[80]; 39 | char *p; 40 | short pos; 41 | 42 | pos = savescreen(&p); 43 | getcwd(olddir, sizeof(olddir)); 44 | cputs("\r\n\r\nType EXIT to quit from this shell\r\n"); 45 | comspec = getenv("COMSPEC"); 46 | system(comspec); 47 | chdir(olddir); 48 | restorescreen(p, pos); 49 | } 50 | -------------------------------------------------------------------------------- /ssh2d386.lnk: -------------------------------------------------------------------------------- 1 | System causeway 2 | Name ssh2d386.exe 3 | Debug all 4 | Option map 5 | File ssh2dos.obj 6 | Library crypto.lib,misc.lib,ssh.lib,vt100.lib,zlib_f.lib,wattcpwf.lib 7 | -------------------------------------------------------------------------------- /ssh2dos.c: -------------------------------------------------------------------------------- 1 | /* ssh2dos.c Copyright (c) 2000-2003 Nagy Daniel 2 | * 3 | * $Date: 2005/12/30 16:26:41 $ 4 | * $Revision: 1.8 $ 5 | * 6 | * This module is the main part: 7 | * - command line parsing 8 | * - client loop 9 | * - running remote command or interactive session 10 | * 11 | * This program is free software; you can redistribute it and/or 12 | * modify it under the terms of the GNU General Public License 13 | * as published by the Free Software Foundation; either version 2 14 | * of the License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Library General Public 22 | * License along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "tcp.h" 35 | #include "ssh.h" 36 | #include "transprt.h" 37 | #include "version.h" 38 | #include "channel.h" 39 | #include "config.h" 40 | #include "common.h" 41 | #include "negotiat.h" 42 | #include "vidio.h" 43 | #include "vttio.h" 44 | #include "keyio.h" 45 | #include "keymap.h" 46 | #if defined (MEMWATCH) 47 | #include "memwatch.h" 48 | #endif 49 | 50 | /* external functions */ 51 | SendFuncPtr SendPacket; 52 | 53 | /* external structures, variables */ 54 | extern Packet pktin; /* incoming SSH2 packet */ 55 | extern unsigned short statusline; 56 | extern unsigned columns; /* Columns on logical terminal screen */ 57 | extern unsigned lines; /* Lines on logical terminal screen */ 58 | extern unsigned short vidmode; 59 | extern char *protocolerror; 60 | 61 | /* global variables */ 62 | Config GlobalConfig; /* global configuration structure */ 63 | unsigned short Configuration; /* Configuration bits */ 64 | 65 | /* local static variables */ 66 | struct vidmod{ 67 | char *mode; 68 | unsigned short vidmode; 69 | }; 70 | static struct vidmod modes[]={ {"80x25", 3}, 71 | {"80x60", 0x108}, 72 | {"132x25", 0x109}, 73 | {"132x50", 0x10b} }; 74 | static char *command = NULL; 75 | static short tty = 0; 76 | static char *RemoteHost = NULL; 77 | static char *UserName = NULL; 78 | static char *PassWord = NULL; 79 | static char *KeyFile = NULL; 80 | static char *term; 81 | static unsigned short RemotePort = SSH_PORT; 82 | static unsigned short Keepalives = 0; 83 | static FILE *LogFile = NULL; 84 | 85 | volatile int timer = 0; /* increased by timer interrupt */ 86 | void (__interrupt __far *oldhandler)(); /* for old timer interrupt */ 87 | 88 | void __interrupt __far keepalive(void){ 89 | timer++; 90 | _chain_intr(oldhandler); 91 | } 92 | 93 | /* 94 | * Initialize global variables 95 | */ 96 | static void Config_Init(void) 97 | { 98 | term = "xterm"; /* default is "xterm" */ 99 | SendPacket = SSH2_Channel_Send; 100 | GlobalConfig.debugfile = NULL; 101 | GlobalConfig.brailab = NULL; 102 | Configuration = 0; 103 | } 104 | 105 | /* 106 | * Allocate a pseudo terminal 107 | */ 108 | static void SSH2_Request_Pty(char *termtype) 109 | { 110 | if(Configuration & VERBOSE_MODE) 111 | puts("Requesting PTY"); 112 | SSH2_Channel_PktInit(SSH_MSG_CHANNEL_REQUEST); 113 | SSH_putstring("pty-req"); 114 | SSH_putbool(1); 115 | SSH_putstring(termtype); 116 | SSH_putuint32(columns); 117 | SSH_putuint32(lines - statusline); 118 | SSH_putuint32(0); 119 | SSH_putuint32(0); 120 | SSH_putstring("\0"); 121 | SSH_pkt_send(); 122 | 123 | SSH2_Channel_Read(SSH_MSG_CHANNEL_SUCCESS); 124 | } 125 | 126 | /* 127 | * Start interactive shell or run command 128 | */ 129 | static void SSH2_Start_Shell_Or_Command(void) 130 | { 131 | if(command != NULL && command[0] != '\0') { 132 | if(Configuration & VERBOSE_MODE) 133 | puts("Running command"); 134 | SSH2_Channel_PktInit(SSH_MSG_CHANNEL_REQUEST); 135 | SSH_putstring("exec"); 136 | SSH_putbool(1); 137 | SSH_putstring(command); 138 | free(command); 139 | } else { 140 | if(Configuration & VERBOSE_MODE) 141 | puts("Running shell"); 142 | SSH2_Channel_PktInit(SSH_MSG_CHANNEL_REQUEST); 143 | SSH_putstring("shell"); 144 | SSH_putbool(1); 145 | } 146 | SSH_pkt_send(); 147 | 148 | SSH2_Channel_Read(SSH_MSG_CHANNEL_SUCCESS); 149 | 150 | } 151 | 152 | /* 153 | * Client loop. This runs when the user successfully logged in, 154 | * until SSH connection is terminated 155 | */ 156 | static short dosession(void) 157 | { 158 | char *str; 159 | unsigned long len; 160 | unsigned short i; 161 | 162 | do{ 163 | /* send keepalive SSH_MSG_IGNORE packet if configured */ 164 | if( timer > Keepalives ){ 165 | SSH_pkt_init(SSH_MSG_IGNORE); 166 | SSH_putstring("keepalive"); 167 | SSH_pkt_send(); 168 | timer = 0; 169 | } /* if */ 170 | 171 | if(!tcp_tick(&GlobalConfig.s)){ /* TCP wait */ 172 | puts("Remote host closed connection"); 173 | return(EXIT_SSH); 174 | } 175 | while(ConChk()) /* examine STDIN */ 176 | DoKey(); 177 | } while(!sock_dataready(&GlobalConfig.s)); 178 | 179 | SbkSetPage(-1); 180 | 181 | SSH2_Channel_Read(0); /* uncrypt and get valuable data */ 182 | 183 | switch(pktin.type){ 184 | case SSH_MSG_CHANNEL_EXTENDED_DATA: 185 | pktin.ptr += 4; 186 | case SSH_MSG_CHANNEL_DATA: /* we got data to display */ 187 | SSH_getstring(&str, &len); /* get and display data */ 188 | for (i = 0; i < len; i++){ 189 | if(tty) 190 | ConOut(str[i]); 191 | else 192 | putchar(str[i]); 193 | } 194 | if(LogFile) 195 | fwrite(str, 1, len, LogFile); 196 | break; 197 | 198 | case SSH_MSG_IGNORE: 199 | break; 200 | 201 | case SSH_MSG_CHANNEL_CLOSE: /* channel is closed */ 202 | SSH_Disconnect(SSH_DISCONNECT_BY_APPLICATION, ""); 203 | return(EXIT_SSH); 204 | 205 | } /* switch */ 206 | return(0); 207 | 208 | } 209 | 210 | /* 211 | * Get command line arguments 212 | */ 213 | static void getargs(int argc, char *argv[]) 214 | { 215 | unsigned short n, i, j, len; 216 | char *s; 217 | #if defined (__386__) 218 | char usage[]="Usage: ssh2d386 [options] username remotehost [command [args]]\n" 219 | #else 220 | char usage[]="Usage: ssh2dos [options] username remotehost [command [args]]\n" 221 | #endif 222 | "Options:\n" 223 | "-i - key file for public key authentication\n" 224 | "-t - terminal type (default: xterm)\n" 225 | "-p - remote port\n" 226 | "-k - path to keymap file\n" 227 | "-m - screen mode: 80x25 80x60 132x25 132x50\n" 228 | "-s - remote password\n" 229 | "-l - log session to file\n" 230 | "-a - time between keepalive packets\n" 231 | "-b - Brailab PC adapter on COM[1234] port\n" 232 | "-P - don't allocate a privileged port\n" 233 | "-C - enable compression\n" 234 | "-S - disable status line\n" 235 | "-B - use BIOS calls for video output\n" 236 | "-V - disable VESA BIOS\n" 237 | "-n - add CR if server sends only LF\n" 238 | "-d - save SSH packets to debug.pkt\n" 239 | "-v - verbose output"; 240 | 241 | for (i = 1; i < argc; ++i){ 242 | s = argv[i]; 243 | if(*s != '-') 244 | break; 245 | switch (*++s){ 246 | case '\0': 247 | fatal(usage); 248 | 249 | case 'i': 250 | if(*++s) 251 | KeyFile = s; 252 | else if(++i < argc) 253 | KeyFile = argv[i]; 254 | else 255 | fatal(usage); 256 | continue; 257 | 258 | case 's': 259 | if(*++s) 260 | PassWord = strdup(s); 261 | else if(++i < argc) 262 | PassWord = strdup(argv[i]); 263 | else 264 | fatal(usage); 265 | PassWord[MAX_PASSWORD_LENGTH - 1] = '\0'; 266 | continue; 267 | 268 | case 'l': 269 | if(*++s){ 270 | if((LogFile = fopen(s,"w+b")) == NULL) 271 | fatal("Cannot create log file"); 272 | } 273 | else if(++i < argc){ 274 | if((LogFile = fopen(argv[i],"w+b")) == NULL) 275 | fatal("Cannot create log file"); 276 | } 277 | else 278 | fatal(usage); 279 | continue; 280 | 281 | case 't': 282 | if(*++s) 283 | term = s; 284 | else if(++i < argc) 285 | term = argv[i]; 286 | else 287 | fatal(usage); 288 | continue; 289 | 290 | case 'm': 291 | if(*++s){ 292 | for(n = 0; n < 4; n++) 293 | if(!strcmp(s, modes[n].mode)){ 294 | vidmode = modes[n].vidmode; 295 | break; 296 | } 297 | if(!vidmode) 298 | fatal(usage); 299 | } 300 | else if(++i < argc){ 301 | for(n = 0; n < 4; n++) 302 | if(!strcmp(argv[i], modes[n].mode)){ 303 | vidmode = modes[n].vidmode; 304 | break; 305 | } 306 | if(!vidmode) 307 | fatal(usage); 308 | } 309 | else 310 | fatal(usage); 311 | continue; 312 | 313 | case 'p': 314 | if(*++s) 315 | RemotePort = atoi(s); 316 | else if(++i < argc) 317 | RemotePort = atoi(argv[i]); 318 | else 319 | fatal(usage); 320 | continue; 321 | 322 | case 'a': 323 | if(*++s) 324 | Keepalives = atoi(s); 325 | else if(++i < argc) 326 | Keepalives = atoi(argv[i]); 327 | else 328 | fatal(usage); 329 | continue; 330 | 331 | case 'b': 332 | if(*++s){ 333 | strupr(s); 334 | if(!strcmp(s, "COM1") || 335 | !strcmp(s, "COM2") || 336 | !strcmp(s, "COM3") || 337 | !strcmp(s, "COM4")){ 338 | if((GlobalConfig.brailab = fopen(s,"w+b")) == NULL){ 339 | fatal("Cannot open COM port"); 340 | } 341 | } 342 | else 343 | fatal(usage); 344 | } 345 | else if(++i < argc){ 346 | strupr(argv[i]); 347 | if(!strcmp(argv[i], "COM1") || 348 | !strcmp(argv[i], "COM2") || 349 | !strcmp(argv[i], "COM3") || 350 | !strcmp(argv[i], "COM4")){ 351 | if((GlobalConfig.brailab = fopen(argv[i],"w+b")) == NULL){ 352 | fatal("Cannot open COM port"); 353 | } 354 | } 355 | else 356 | fatal(usage); 357 | } 358 | else 359 | fatal(usage); 360 | continue; 361 | 362 | case 'k': 363 | if(*++s) 364 | keymap_init(s); 365 | else if(++i < argc) 366 | keymap_init(argv[i]); 367 | else 368 | fatal(usage); 369 | continue; 370 | 371 | case 'P': 372 | Configuration += NONPRIVILEGED_PORT; 373 | continue; 374 | 375 | case 'S': 376 | statusline = 0; 377 | continue; 378 | 379 | case 'C': 380 | Configuration += COMPRESSION_REQUESTED; 381 | continue; 382 | 383 | case 'B': 384 | Configuration += BIOS; 385 | continue; 386 | 387 | case 'V': 388 | Configuration += NOVESA; 389 | continue; 390 | 391 | case 'n': 392 | Configuration += NEWLINE; 393 | continue; 394 | 395 | case 'd': 396 | if((GlobalConfig.debugfile = fopen("debug.pkt","w+")) == NULL) 397 | fatal("Cannot create debug file"); 398 | else 399 | fputs("\n-------------------\n",GlobalConfig.debugfile); 400 | continue; 401 | 402 | case 'v': 403 | Configuration += VERBOSE_MODE; 404 | continue; 405 | 406 | default: 407 | fatal(usage); 408 | } /* end switch */ 409 | 410 | } /* end for */ 411 | 412 | /* no_more_options */ 413 | if(i + 2 > argc) 414 | fatal(usage); 415 | UserName = argv[i++]; 416 | RemoteHost = argv[i++]; 417 | if(i >= argc) /* command args? */ 418 | return; 419 | /* collect remaining arguments and make a command line of them */ 420 | for(len = 0, j = i; j < argc; j++) 421 | len += strlen(argv[j]) + 1; /* 1 for the separating space */ 422 | if((command = (char *)malloc(len)) == NULL) 423 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 424 | for(*command = '\0', j = i; j < argc; j++){ 425 | strcat(command, argv[j]); /* inefficient, but no big deal */ 426 | if(j < argc - 1) /* last argument? */ 427 | strcat(command, " "); 428 | } 429 | } 430 | 431 | /* 432 | * Main program starts here 433 | */ 434 | int main(int argc, char **argv) 435 | { 436 | #if defined (__386__) 437 | printf("SSH2DOS v%s. 386+ version\n", SSH_VERSION); 438 | #else 439 | printf("SSH2DOS v%s\n", SSH_VERSION); 440 | #endif 441 | printf("%s\n", AUTHOR_1); 442 | printf("%s\n\n", AUTHOR_2); 443 | 444 | Config_Init(); /* Initialize global variables */ 445 | srand(time(NULL)); /* Initialize random number generator */ 446 | 447 | getargs(argc, argv); /* Process command line */ 448 | 449 | VESACheck(); 450 | SetMode(); 451 | VidParam(); /* Get proper screen size for PTY negotiation */ 452 | 453 | TCPConnect(RemoteHost, RemotePort); /* Connect to server */ 454 | 455 | SSH_Connect(UserName, PassWord, KeyFile); /* Start SSH negotiation */ 456 | 457 | /* Request a pseudo terminal */ 458 | if(isatty(fileno(stdout))) 459 | tty = 1; 460 | SSH2_Request_Pty(term); 461 | 462 | /* Start an interactive shell or run specified command */ 463 | SSH2_Start_Shell_Or_Command(); 464 | 465 | tcp_cbreak(1); /* No Break checking */ 466 | 467 | VidInit(UserName, RemoteHost); 468 | VTInit(); 469 | 470 | if(Keepalives){ /* install keepalive timer */ 471 | Keepalives = Keepalives * 18 * 60; /* correct keepalives value */ 472 | oldhandler = _dos_getvect(0x1C); 473 | _dos_setvect(0x1C, keepalive); 474 | } /* if */ 475 | 476 | while(EXIT_SSH != dosession()); /* Loop until session end */ 477 | 478 | free(pktin.body); 479 | 480 | VidUninit(); 481 | keymap_uninit(); 482 | 483 | if(Configuration & COMPRESSION_ENABLED) 484 | Disable_Compression(); 485 | 486 | if(Keepalives) 487 | _dos_setvect(0x1C, oldhandler); 488 | 489 | sock_close(&GlobalConfig.s); /* Close TCP socket */ 490 | 491 | tcp_cbreak(0x10); /* Break checking on */ 492 | 493 | /* Close open files */ 494 | if(GlobalConfig.brailab) 495 | fclose(GlobalConfig.brailab); 496 | if(GlobalConfig.debugfile) 497 | fclose(GlobalConfig.debugfile); 498 | if(LogFile) 499 | fclose(LogFile); 500 | 501 | return(0); 502 | } 503 | -------------------------------------------------------------------------------- /ssh2dos.lnk: -------------------------------------------------------------------------------- 1 | System dos 2 | Name ssh2dos.exe 3 | Debug all 4 | File ssh2dos.obj 5 | Option map 6 | Library crypto.lib,misc.lib,ssh.lib,vt100.lib,zlib_l.lib,wattcpwl.lib 7 | Option Stack=4k 8 | -------------------------------------------------------------------------------- /sshdss.c: -------------------------------------------------------------------------------- 1 | /* 2 | * DSS key routines 3 | * 4 | * Taken from the PuTTY source. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "pubkey.h" 13 | #include "sshsha.h" 14 | #include "ssh.h" 15 | #include "macros.h" 16 | #include "common.h" 17 | #if defined (MEMWATCH) 18 | #include "memwatch.h" 19 | #endif 20 | 21 | extern struct ssh2_userkey ssh2_wrong_passphrase; 22 | 23 | struct dss_key { 24 | Bignum p, q, g, y, x; 25 | }; 26 | 27 | static void sha_mpint2(SHA_State * s, Bignum b) 28 | { 29 | unsigned char lenbuf[4]; 30 | int len; 31 | len = (bignum_bitcount(b) + 8) / 8; 32 | PUT_32BIT_MSB_FIRST(lenbuf, len); 33 | SHA_Bytes(s, lenbuf, 4); 34 | while (len-- > 0) { 35 | lenbuf[0] = bignum_byte(b, len); 36 | SHA_Bytes(s, lenbuf, 1); 37 | } 38 | memset(lenbuf, 0, sizeof(lenbuf)); 39 | } 40 | 41 | static void sha512_mpint(SHA512_State * s, Bignum b) 42 | { 43 | unsigned char lenbuf[4]; 44 | int len; 45 | len = (bignum_bitcount(b) + 8) / 8; 46 | PUT_32BIT_MSB_FIRST(lenbuf, len); 47 | SHA512_Bytes(s, lenbuf, 4); 48 | while (len-- > 0) { 49 | lenbuf[0] = bignum_byte(b, len); 50 | SHA512_Bytes(s, lenbuf, 1); 51 | } 52 | memset(lenbuf, 0, sizeof(lenbuf)); 53 | } 54 | 55 | static void getstring(char **data, int *datalen, char **p, int *length) 56 | { 57 | *p = NULL; 58 | if (*datalen < 4) 59 | return; 60 | *length = GET_32BIT_MSB_FIRST(*data); 61 | *datalen -= 4; 62 | *data += 4; 63 | if (*datalen < *length) 64 | return; 65 | *p = *data; 66 | *data += *length; 67 | *datalen -= *length; 68 | } 69 | static Bignum getmp(char **data, int *datalen) 70 | { 71 | char *p; 72 | int length; 73 | Bignum b; 74 | 75 | getstring(data, datalen, &p, &length); 76 | if (!p) 77 | return NULL; 78 | if (p[0] & 0x80) 79 | return NULL; /* negative mp */ 80 | b = bignum_from_bytes(p, length); 81 | return b; 82 | } 83 | 84 | static void *dss_newkey(char *data, int len) 85 | { 86 | char *p; 87 | int slen; 88 | struct dss_key *dss; 89 | 90 | if((dss = (struct dss_key *)malloc(sizeof(struct dss_key))) == NULL) 91 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 92 | if (!dss) 93 | return NULL; 94 | getstring(&data, &len, &p, &slen); 95 | 96 | #ifdef DEBUG_DSS 97 | { 98 | int i; 99 | printf("key:"); 100 | for (i = 0; i < len; i++) 101 | printf(" %02x", (unsigned char) (data[i])); 102 | printf("\n"); 103 | } 104 | #endif 105 | 106 | if (!p || memcmp(p, "ssh-dss", 7)) { 107 | free(dss); 108 | return NULL; 109 | } 110 | dss->p = getmp(&data, &len); 111 | dss->q = getmp(&data, &len); 112 | dss->g = getmp(&data, &len); 113 | dss->y = getmp(&data, &len); 114 | 115 | return dss; 116 | } 117 | 118 | static void dss_freekey(void *key) 119 | { 120 | struct dss_key *dss = (struct dss_key *) key; 121 | freebn(dss->p); 122 | freebn(dss->q); 123 | freebn(dss->g); 124 | freebn(dss->y); 125 | free(dss); 126 | } 127 | 128 | static unsigned char *dss_public_blob(void *key, int *len) 129 | { 130 | struct dss_key *dss = (struct dss_key *) key; 131 | int plen, qlen, glen, ylen, bloblen; 132 | int i; 133 | unsigned char *blob, *p; 134 | 135 | plen = (bignum_bitcount(dss->p) + 8) / 8; 136 | qlen = (bignum_bitcount(dss->q) + 8) / 8; 137 | glen = (bignum_bitcount(dss->g) + 8) / 8; 138 | ylen = (bignum_bitcount(dss->y) + 8) / 8; 139 | 140 | /* 141 | * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total 142 | * 27 + sum of lengths. (five length fields, 20+7=27). 143 | */ 144 | bloblen = 27 + plen + qlen + glen + ylen; 145 | if((blob = (unsigned char *)malloc(bloblen)) == NULL) 146 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 147 | p = blob; 148 | PUT_32BIT_MSB_FIRST(p, 7); 149 | p += 4; 150 | memcpy(p, "ssh-dss", 7); 151 | p += 7; 152 | PUT_32BIT_MSB_FIRST(p, plen); 153 | p += 4; 154 | for (i = plen; i--;) 155 | *p++ = bignum_byte(dss->p, i); 156 | PUT_32BIT_MSB_FIRST(p, qlen); 157 | p += 4; 158 | for (i = qlen; i--;) 159 | *p++ = bignum_byte(dss->q, i); 160 | PUT_32BIT_MSB_FIRST(p, glen); 161 | p += 4; 162 | for (i = glen; i--;) 163 | *p++ = bignum_byte(dss->g, i); 164 | PUT_32BIT_MSB_FIRST(p, ylen); 165 | p += 4; 166 | for (i = ylen; i--;) 167 | *p++ = bignum_byte(dss->y, i); 168 | assert(p == blob + bloblen); 169 | *len = bloblen; 170 | return blob; 171 | } 172 | 173 | static void *dss_createkey(unsigned char *pub_blob, int pub_len, 174 | unsigned char *priv_blob, int priv_len) 175 | { 176 | struct dss_key *dss; 177 | char *pb = (char *) priv_blob; 178 | char *hash; 179 | int hashlen; 180 | SHA_State s; 181 | unsigned char digest[20]; 182 | Bignum ytest; 183 | 184 | dss = dss_newkey((char *) pub_blob, pub_len); 185 | dss->x = getmp(&pb, &priv_len); 186 | 187 | /* 188 | * Check the obsolete hash in the old DSS key format. 189 | */ 190 | hashlen = -1; 191 | getstring(&pb, &priv_len, &hash, &hashlen); 192 | if (hashlen == 20) { 193 | SHA_Init(&s); 194 | sha_mpint2(&s, dss->p); 195 | sha_mpint2(&s, dss->q); 196 | sha_mpint2(&s, dss->g); 197 | SHA_Final(&s, digest); 198 | if (0 != memcmp(hash, digest, 20)) { 199 | dss_freekey(dss); 200 | return NULL; 201 | } 202 | } 203 | 204 | /* 205 | * Now ensure g^x mod p really is y. 206 | */ 207 | ytest = modpow(dss->g, dss->x, dss->p); 208 | if (0 != bignum_cmp(ytest, dss->y)) { 209 | dss_freekey(dss); 210 | return NULL; 211 | } 212 | freebn(ytest); 213 | 214 | return dss; 215 | } 216 | 217 | unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) 218 | { 219 | /* 220 | * The basic DSS signing algorithm is: 221 | * 222 | * - invent a random k between 1 and q-1 (exclusive). 223 | * - Compute r = (g^k mod p) mod q. 224 | * - Compute s = k^-1 * (hash + x*r) mod q. 225 | * 226 | * This has the dangerous properties that: 227 | * 228 | * - if an attacker in possession of the public key _and_ the 229 | * signature (for example, the host you just authenticated 230 | * to) can guess your k, he can reverse the computation of s 231 | * and work out x = r^-1 * (s*k - hash) mod q. That is, he 232 | * can deduce the private half of your key, and masquerade 233 | * as you for as long as the key is still valid. 234 | * 235 | * - since r is a function purely of k and the public key, if 236 | * the attacker only has a _range of possibilities_ for k 237 | * it's easy for him to work through them all and check each 238 | * one against r; he'll never be unsure of whether he's got 239 | * the right one. 240 | * 241 | * - if you ever sign two different hashes with the same k, it 242 | * will be immediately obvious because the two signatures 243 | * will have the same r, and moreover an attacker in 244 | * possession of both signatures (and the public key of 245 | * course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q, 246 | * and from there deduce x as before. 247 | * 248 | * - the Bleichenbacher attack on DSA makes use of methods of 249 | * generating k which are significantly non-uniformly 250 | * distributed; in particular, generating a 160-bit random 251 | * number and reducing it mod q is right out. 252 | * 253 | * For this reason we must be pretty careful about how we 254 | * generate our k. Since this code runs on Windows, with no 255 | * particularly good system entropy sources, we can't trust our 256 | * RNG itself to produce properly unpredictable data. Hence, we 257 | * use a totally different scheme instead. 258 | * 259 | * What we do is to take a SHA-512 (_big_) hash of the private 260 | * key x, and then feed this into another SHA-512 hash that 261 | * also includes the message hash being signed. That is: 262 | * 263 | * proto_k = SHA512 ( SHA512(x) || SHA160(message) ) 264 | * 265 | * This number is 512 bits long, so reducing it mod q won't be 266 | * noticeably non-uniform. So 267 | * 268 | * k = proto_k mod q 269 | * 270 | * This has the interesting property that it's _deterministic_: 271 | * signing the same hash twice with the same key yields the 272 | * same signature. 273 | * 274 | * Despite this determinism, it's still not predictable to an 275 | * attacker, because in order to repeat the SHA-512 276 | * construction that created it, the attacker would have to 277 | * know the private key value x - and by assumption he doesn't, 278 | * because if he knew that he wouldn't be attacking k! 279 | * 280 | * (This trick doesn't, _per se_, protect against reuse of k. 281 | * Reuse of k is left to chance; all it does is prevent 282 | * _excessively high_ chances of reuse of k due to entropy 283 | * problems.) 284 | * 285 | * Thanks to Colin Plumb for the general idea of using x to 286 | * ensure k is hard to guess, and to the Cambridge University 287 | * Computer Security Group for helping to argue out all the 288 | * fine details. 289 | */ 290 | struct dss_key *dss = (struct dss_key *) key; 291 | SHA512_State ss; 292 | unsigned char digest[20], digest512[64]; 293 | Bignum proto_k, k, gkp, hash, kinv, hxr, r, s; 294 | unsigned char *bytes; 295 | int nbytes, i; 296 | 297 | SHA_Simple(data, datalen, digest); 298 | 299 | /* 300 | * Hash some identifying text plus x. 301 | */ 302 | SHA512_Init(&ss); 303 | SHA512_Bytes(&ss, "DSA deterministic k generator", 30); 304 | sha512_mpint(&ss, dss->x); 305 | SHA512_Final(&ss, digest512); 306 | 307 | /* 308 | * Now hash that digest plus the message hash. 309 | */ 310 | SHA512_Init(&ss); 311 | SHA512_Bytes(&ss, digest512, sizeof(digest512)); 312 | SHA512_Bytes(&ss, digest, sizeof(digest)); 313 | SHA512_Final(&ss, digest512); 314 | 315 | memset(&ss, 0, sizeof(ss)); 316 | 317 | /* 318 | * Now convert the result into a bignum, and reduce it mod q. 319 | */ 320 | proto_k = bignum_from_bytes(digest512, 64); 321 | k = bigmod(proto_k, dss->q); 322 | freebn(proto_k); 323 | 324 | memset(digest512, 0, sizeof(digest512)); 325 | 326 | /* 327 | * Now we have k, so just go ahead and compute the signature. 328 | */ 329 | gkp = modpow(dss->g, k, dss->p); /* g^k mod p */ 330 | r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */ 331 | freebn(gkp); 332 | 333 | hash = bignum_from_bytes(digest, 20); 334 | kinv = modinv(k, dss->q); /* k^-1 mod q */ 335 | free(k); 336 | hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */ 337 | s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */ 338 | freebn(hxr); 339 | freebn(kinv); 340 | freebn(hash); 341 | 342 | /* 343 | * Signature blob is 344 | * 345 | * string "ssh-dss" 346 | * string two 20-byte numbers r and s, end to end 347 | * 348 | * i.e. 4+7 + 4+40 bytes. 349 | */ 350 | nbytes = 4 + 7 + 4 + 40; 351 | if((bytes = malloc(nbytes)) == NULL) 352 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 353 | PUT_32BIT_MSB_FIRST(bytes, 7); 354 | memcpy(bytes + 4, "ssh-dss", 7); 355 | PUT_32BIT_MSB_FIRST(bytes + 4 + 7, 40); 356 | for (i = 0; i < 20; i++) { 357 | bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i); 358 | bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i); 359 | } 360 | freebn(r); 361 | freebn(s); 362 | 363 | *siglen = nbytes; 364 | return bytes; 365 | } 366 | 367 | const struct ssh_signkey ssh_dss = { 368 | dss_public_blob, 369 | dss_createkey, 370 | dss_sign, 371 | "ssh-dss", 372 | }; 373 | -------------------------------------------------------------------------------- /sshmd5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MD5 implementation for PuTTY. Written directly from the spec by 3 | * Simon Tatham. 4 | */ 5 | 6 | #include 7 | #include "type.h" 8 | 9 | typedef struct { 10 | uint32 h[4]; 11 | } MD5_Core_State; 12 | 13 | struct MD5Context { 14 | MD5_Core_State core; 15 | unsigned char block[64]; 16 | int blkused; 17 | uint32 lenhi, lenlo; 18 | }; 19 | 20 | static struct MD5Context md5c; 21 | 22 | /* ---------------------------------------------------------------------- 23 | * Core MD5 algorithm: processes 16-word blocks into a message digest. 24 | */ 25 | 26 | #define F(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) ) 27 | #define G(x,y,z) ( ((x) & (z)) | ((~(z)) & (y)) ) 28 | #define H(x,y,z) ( (x) ^ (y) ^ (z) ) 29 | #define I(x,y,z) ( (y) ^ ( (x) | ~(z) ) ) 30 | 31 | #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) ) 32 | 33 | #define subround(f,w,x,y,z,k,s,ti) \ 34 | w = x + rol(w + f(x,y,z) + block[k] + ti, s) 35 | 36 | void MD5_Core_Init(MD5_Core_State * s) 37 | { 38 | s->h[0] = 0x67452301; 39 | s->h[1] = 0xefcdab89; 40 | s->h[2] = 0x98badcfe; 41 | s->h[3] = 0x10325476; 42 | } 43 | 44 | void MD5_Block(MD5_Core_State * s, uint32 * block) 45 | { 46 | uint32 a, b, c, d; 47 | 48 | a = s->h[0]; 49 | b = s->h[1]; 50 | c = s->h[2]; 51 | d = s->h[3]; 52 | 53 | subround(F, a, b, c, d, 0, 7, 0xd76aa478); 54 | subround(F, d, a, b, c, 1, 12, 0xe8c7b756); 55 | subround(F, c, d, a, b, 2, 17, 0x242070db); 56 | subround(F, b, c, d, a, 3, 22, 0xc1bdceee); 57 | subround(F, a, b, c, d, 4, 7, 0xf57c0faf); 58 | subround(F, d, a, b, c, 5, 12, 0x4787c62a); 59 | subround(F, c, d, a, b, 6, 17, 0xa8304613); 60 | subround(F, b, c, d, a, 7, 22, 0xfd469501); 61 | subround(F, a, b, c, d, 8, 7, 0x698098d8); 62 | subround(F, d, a, b, c, 9, 12, 0x8b44f7af); 63 | subround(F, c, d, a, b, 10, 17, 0xffff5bb1); 64 | subround(F, b, c, d, a, 11, 22, 0x895cd7be); 65 | subround(F, a, b, c, d, 12, 7, 0x6b901122); 66 | subround(F, d, a, b, c, 13, 12, 0xfd987193); 67 | subround(F, c, d, a, b, 14, 17, 0xa679438e); 68 | subround(F, b, c, d, a, 15, 22, 0x49b40821); 69 | subround(G, a, b, c, d, 1, 5, 0xf61e2562); 70 | subround(G, d, a, b, c, 6, 9, 0xc040b340); 71 | subround(G, c, d, a, b, 11, 14, 0x265e5a51); 72 | subround(G, b, c, d, a, 0, 20, 0xe9b6c7aa); 73 | subround(G, a, b, c, d, 5, 5, 0xd62f105d); 74 | subround(G, d, a, b, c, 10, 9, 0x02441453); 75 | subround(G, c, d, a, b, 15, 14, 0xd8a1e681); 76 | subround(G, b, c, d, a, 4, 20, 0xe7d3fbc8); 77 | subround(G, a, b, c, d, 9, 5, 0x21e1cde6); 78 | subround(G, d, a, b, c, 14, 9, 0xc33707d6); 79 | subround(G, c, d, a, b, 3, 14, 0xf4d50d87); 80 | subround(G, b, c, d, a, 8, 20, 0x455a14ed); 81 | subround(G, a, b, c, d, 13, 5, 0xa9e3e905); 82 | subround(G, d, a, b, c, 2, 9, 0xfcefa3f8); 83 | subround(G, c, d, a, b, 7, 14, 0x676f02d9); 84 | subround(G, b, c, d, a, 12, 20, 0x8d2a4c8a); 85 | subround(H, a, b, c, d, 5, 4, 0xfffa3942); 86 | subround(H, d, a, b, c, 8, 11, 0x8771f681); 87 | subround(H, c, d, a, b, 11, 16, 0x6d9d6122); 88 | subround(H, b, c, d, a, 14, 23, 0xfde5380c); 89 | subround(H, a, b, c, d, 1, 4, 0xa4beea44); 90 | subround(H, d, a, b, c, 4, 11, 0x4bdecfa9); 91 | subround(H, c, d, a, b, 7, 16, 0xf6bb4b60); 92 | subround(H, b, c, d, a, 10, 23, 0xbebfbc70); 93 | subround(H, a, b, c, d, 13, 4, 0x289b7ec6); 94 | subround(H, d, a, b, c, 0, 11, 0xeaa127fa); 95 | subround(H, c, d, a, b, 3, 16, 0xd4ef3085); 96 | subround(H, b, c, d, a, 6, 23, 0x04881d05); 97 | subround(H, a, b, c, d, 9, 4, 0xd9d4d039); 98 | subround(H, d, a, b, c, 12, 11, 0xe6db99e5); 99 | subround(H, c, d, a, b, 15, 16, 0x1fa27cf8); 100 | subround(H, b, c, d, a, 2, 23, 0xc4ac5665); 101 | subround(I, a, b, c, d, 0, 6, 0xf4292244); 102 | subround(I, d, a, b, c, 7, 10, 0x432aff97); 103 | subround(I, c, d, a, b, 14, 15, 0xab9423a7); 104 | subround(I, b, c, d, a, 5, 21, 0xfc93a039); 105 | subround(I, a, b, c, d, 12, 6, 0x655b59c3); 106 | subround(I, d, a, b, c, 3, 10, 0x8f0ccc92); 107 | subround(I, c, d, a, b, 10, 15, 0xffeff47d); 108 | subround(I, b, c, d, a, 1, 21, 0x85845dd1); 109 | subround(I, a, b, c, d, 8, 6, 0x6fa87e4f); 110 | subround(I, d, a, b, c, 15, 10, 0xfe2ce6e0); 111 | subround(I, c, d, a, b, 6, 15, 0xa3014314); 112 | subround(I, b, c, d, a, 13, 21, 0x4e0811a1); 113 | subround(I, a, b, c, d, 4, 6, 0xf7537e82); 114 | subround(I, d, a, b, c, 11, 10, 0xbd3af235); 115 | subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb); 116 | subround(I, b, c, d, a, 9, 21, 0xeb86d391); 117 | 118 | s->h[0] += a; 119 | s->h[1] += b; 120 | s->h[2] += c; 121 | s->h[3] += d; 122 | } 123 | 124 | /* ---------------------------------------------------------------------- 125 | * Outer MD5 algorithm: take an arbitrary length byte string, 126 | * convert it into 16-word blocks with the prescribed padding at 127 | * the end, and pass those blocks to the core MD5 algorithm. 128 | */ 129 | 130 | #define BLKSIZE 64 131 | 132 | void MD5Init(void) 133 | { 134 | MD5_Core_Init(&md5c.core); 135 | md5c.blkused = 0; 136 | md5c.lenhi = md5c.lenlo = 0; 137 | } 138 | 139 | void MD5Update(char const *p, unsigned len) 140 | { 141 | unsigned char *q = (unsigned char *) p; 142 | uint32 wordblock[16]; 143 | uint32 lenw = len; 144 | int i; 145 | 146 | /* 147 | * Update the length field. 148 | */ 149 | md5c.lenlo += lenw; 150 | md5c.lenhi += (md5c.lenlo < lenw); 151 | 152 | if (md5c.blkused + len < BLKSIZE) { 153 | /* 154 | * Trivial case: just add to the block. 155 | */ 156 | memcpy(md5c.block + md5c.blkused, q, len); 157 | md5c.blkused += len; 158 | } else { 159 | /* 160 | * We must complete and process at least one block. 161 | */ 162 | while (md5c.blkused + len >= BLKSIZE) { 163 | memcpy(md5c.block + md5c.blkused, q, BLKSIZE - md5c.blkused); 164 | q += BLKSIZE - md5c.blkused; 165 | len -= BLKSIZE - md5c.blkused; 166 | /* Now process the block. Gather bytes little-endian into words */ 167 | for (i = 0; i < 16; i++) { 168 | wordblock[i] = 169 | (((uint32) md5c.block[i * 4 + 3]) << 24) | 170 | (((uint32) md5c.block[i * 4 + 2]) << 16) | 171 | (((uint32) md5c.block[i * 4 + 1]) << 8) | 172 | (((uint32) md5c.block[i * 4 + 0]) << 0); 173 | } 174 | MD5_Block(&md5c.core, wordblock); 175 | md5c.blkused = 0; 176 | } 177 | memcpy(md5c.block, q, len); 178 | md5c.blkused = len; 179 | } 180 | } 181 | 182 | void MD5Final(unsigned char output[16]) 183 | { 184 | int i; 185 | unsigned pad; 186 | unsigned char c[64]; 187 | uint32 lenhi, lenlo; 188 | 189 | if (md5c.blkused >= 56) 190 | pad = 56 + 64 - md5c.blkused; 191 | else 192 | pad = 56 - md5c.blkused; 193 | 194 | lenhi = (md5c.lenhi << 3) | (md5c.lenlo >> (32 - 3)); 195 | lenlo = (md5c.lenlo << 3); 196 | 197 | memset(c, 0, pad); 198 | c[0] = 0x80; 199 | MD5Update(c, pad); 200 | 201 | c[7] = (lenhi >> 24) & 0xFF; 202 | c[6] = (lenhi >> 16) & 0xFF; 203 | c[5] = (lenhi >> 8) & 0xFF; 204 | c[4] = (lenhi >> 0) & 0xFF; 205 | c[3] = (lenlo >> 24) & 0xFF; 206 | c[2] = (lenlo >> 16) & 0xFF; 207 | c[1] = (lenlo >> 8) & 0xFF; 208 | c[0] = (lenlo >> 0) & 0xFF; 209 | 210 | MD5Update(c, 8); 211 | 212 | for (i = 0; i < 4; i++) { 213 | output[4 * i + 3] = (md5c.core.h[i] >> 24) & 0xFF; 214 | output[4 * i + 2] = (md5c.core.h[i] >> 16) & 0xFF; 215 | output[4 * i + 1] = (md5c.core.h[i] >> 8) & 0xFF; 216 | output[4 * i + 0] = (md5c.core.h[i] >> 0) & 0xFF; 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /sshrsa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * RSA implementation just sufficient for ssh client-side 3 | * initialisation step 4 | * 5 | * Rewritten for more speed by Joris van Rantwijk, Jun 1999. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "ssh.h" 14 | #include "sshsha.h" 15 | #include "macros.h" 16 | #include "pubkey.h" 17 | #include "common.h" 18 | #if defined (MEMWATCH) 19 | #include "memwatch.h" 20 | #endif 21 | 22 | extern Bignum One; 23 | extern struct ssh2_userkey ssh2_wrong_passphrase; 24 | 25 | struct RSAKey { 26 | int bits; 27 | int bytes; 28 | Bignum modulus; 29 | Bignum exponent; 30 | Bignum private_exponent; 31 | Bignum p; 32 | Bignum q; 33 | Bignum iqmp; 34 | char *comment; 35 | }; 36 | 37 | /* 38 | * Verify that the public data in an RSA key matches the private 39 | * data. We also check the private data itself: we ensure that p > 40 | * q and that iqmp really is the inverse of q mod p. 41 | */ 42 | int rsa_verify(struct RSAKey *key) 43 | { 44 | Bignum n, ed, pm1, qm1; 45 | int cmp; 46 | 47 | /* n must equal pq. */ 48 | n = bigmul(key->p, key->q); 49 | cmp = bignum_cmp(n, key->modulus); 50 | freebn(n); 51 | if (cmp != 0) 52 | return 0; 53 | 54 | /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */ 55 | pm1 = copybn(key->p); 56 | decbn(pm1); 57 | ed = modmul(key->exponent, key->private_exponent, pm1); 58 | cmp = bignum_cmp(ed, One); 59 | free(ed); 60 | if (cmp != 0) 61 | return 0; 62 | 63 | qm1 = copybn(key->q); 64 | decbn(qm1); 65 | ed = modmul(key->exponent, key->private_exponent, qm1); 66 | cmp = bignum_cmp(ed, One); 67 | free(ed); 68 | if (cmp != 0) 69 | return 0; 70 | 71 | /* 72 | * Ensure p > q. 73 | */ 74 | if (bignum_cmp(key->p, key->q) <= 0) 75 | return 0; 76 | 77 | /* 78 | * Ensure iqmp * q is congruent to 1, modulo p. 79 | */ 80 | n = modmul(key->iqmp, key->q, key->p); 81 | cmp = bignum_cmp(n, One); 82 | free(n); 83 | if (cmp != 0) 84 | return 0; 85 | 86 | return 1; 87 | } 88 | 89 | void freersakey(struct RSAKey *key) 90 | { 91 | if (key->modulus) 92 | freebn(key->modulus); 93 | if (key->exponent) 94 | freebn(key->exponent); 95 | if (key->private_exponent) 96 | freebn(key->private_exponent); 97 | if (key->comment) 98 | free(key->comment); 99 | } 100 | 101 | /* ---------------------------------------------------------------------- 102 | * Implementation of the ssh-rsa signing key type. 103 | */ 104 | 105 | static void getstring(char **data, int *datalen, char **p, int *length) 106 | { 107 | *p = NULL; 108 | if (*datalen < 4) 109 | return; 110 | *length = GET_32BIT_MSB_FIRST(*data); 111 | *datalen -= 4; 112 | *data += 4; 113 | if (*datalen < *length) 114 | return; 115 | *p = *data; 116 | *data += *length; 117 | *datalen -= *length; 118 | } 119 | static Bignum getmp(char **data, int *datalen) 120 | { 121 | char *p; 122 | int length; 123 | Bignum b; 124 | 125 | getstring(data, datalen, &p, &length); 126 | if (!p) 127 | return NULL; 128 | b = bignum_from_bytes(p, length); 129 | return b; 130 | } 131 | 132 | static void *rsa2_newkey(char *data, int len) 133 | { 134 | char *p; 135 | int slen; 136 | struct RSAKey *rsa; 137 | 138 | if((rsa = malloc(sizeof(struct RSAKey))) == NULL) 139 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 140 | getstring(&data, &len, &p, &slen); 141 | 142 | if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) { 143 | free(rsa); 144 | return NULL; 145 | } 146 | rsa->exponent = getmp(&data, &len); 147 | rsa->modulus = getmp(&data, &len); 148 | rsa->private_exponent = NULL; 149 | rsa->comment = NULL; 150 | 151 | return rsa; 152 | } 153 | 154 | static void rsa2_freekey(void *key) 155 | { 156 | struct RSAKey *rsa = (struct RSAKey *) key; 157 | freersakey(rsa); 158 | free(rsa); 159 | } 160 | 161 | static unsigned char *rsa2_public_blob(void *key, int *len) 162 | { 163 | struct RSAKey *rsa = (struct RSAKey *) key; 164 | int elen, mlen, bloblen; 165 | int i; 166 | unsigned char *blob, *p; 167 | 168 | elen = (bignum_bitcount(rsa->exponent) + 8) / 8; 169 | mlen = (bignum_bitcount(rsa->modulus) + 8) / 8; 170 | 171 | /* 172 | * string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen. 173 | * (three length fields, 12+7=19). 174 | */ 175 | bloblen = 19 + elen + mlen; 176 | if((blob = malloc(bloblen)) == NULL) 177 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 178 | p = blob; 179 | PUT_32BIT_MSB_FIRST(p, 7); 180 | p += 4; 181 | memcpy(p, "ssh-rsa", 7); 182 | p += 7; 183 | PUT_32BIT_MSB_FIRST(p, elen); 184 | p += 4; 185 | for (i = elen; i--;) 186 | *p++ = bignum_byte(rsa->exponent, i); 187 | PUT_32BIT_MSB_FIRST(p, mlen); 188 | p += 4; 189 | for (i = mlen; i--;) 190 | *p++ = bignum_byte(rsa->modulus, i); 191 | assert(p == blob + bloblen); 192 | *len = bloblen; 193 | return blob; 194 | } 195 | 196 | static void *rsa2_createkey(unsigned char *pub_blob, int pub_len, 197 | unsigned char *priv_blob, int priv_len) 198 | { 199 | struct RSAKey *rsa; 200 | char *pb = (char *) priv_blob; 201 | 202 | rsa = rsa2_newkey((char *) pub_blob, pub_len); 203 | rsa->private_exponent = getmp(&pb, &priv_len); 204 | rsa->p = getmp(&pb, &priv_len); 205 | rsa->q = getmp(&pb, &priv_len); 206 | rsa->iqmp = getmp(&pb, &priv_len); 207 | 208 | if (!rsa_verify(rsa)) { 209 | rsa2_freekey(rsa); 210 | return NULL; 211 | } 212 | 213 | return rsa; 214 | } 215 | 216 | /* 217 | * This is the magic ASN.1/DER prefix that goes in the decoded 218 | * signature, between the string of FFs and the actual SHA hash 219 | * value. The meaning of it is: 220 | * 221 | * 00 -- this marks the end of the FFs; not part of the ASN.1 bit itself 222 | * 223 | * 30 21 -- a constructed SEQUENCE of length 0x21 224 | * 30 09 -- a constructed sub-SEQUENCE of length 9 225 | * 06 05 -- an object identifier, length 5 226 | * 2B 0E 03 02 1A -- object id { 1 3 14 3 2 26 } 227 | * (the 1,3 comes from 0x2B = 43 = 40*1+3) 228 | * 05 00 -- NULL 229 | * 04 14 -- a primitive OCTET STRING of length 0x14 230 | * [0x14 bytes of hash data follows] 231 | * 232 | * The object id in the middle there is listed as `id-sha1' in 233 | * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2.asn (the 234 | * ASN module for PKCS #1) and its expanded form is as follows: 235 | * 236 | * id-sha1 OBJECT IDENTIFIER ::= { 237 | * iso(1) identified-organization(3) oiw(14) secsig(3) 238 | * algorithms(2) 26 } 239 | */ 240 | static unsigned char asn1_weird_stuff[] = { 241 | 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 242 | 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14, 243 | }; 244 | 245 | #define ASN1_LEN ( (int) sizeof(asn1_weird_stuff) ) 246 | 247 | unsigned char *rsa2_sign(void *key, char *data, int datalen, int *siglen) 248 | { 249 | struct RSAKey *rsa = (struct RSAKey *) key; 250 | unsigned char *bytes; 251 | int nbytes; 252 | unsigned char hash[20]; 253 | Bignum in, out; 254 | int i, j; 255 | 256 | SHA_Simple(data, datalen, hash); 257 | 258 | nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8; 259 | if((bytes = malloc(nbytes)) == NULL) 260 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 261 | 262 | bytes[0] = 1; 263 | for (i = 1; i < nbytes - 20 - ASN1_LEN; i++) 264 | bytes[i] = 0xFF; 265 | for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++) 266 | bytes[i] = asn1_weird_stuff[j]; 267 | for (i = nbytes - 20, j = 0; i < nbytes; i++, j++) 268 | bytes[i] = hash[j]; 269 | 270 | in = bignum_from_bytes(bytes, nbytes); 271 | free(bytes); 272 | 273 | out = modpow(in, rsa->private_exponent, rsa->modulus); 274 | freebn(in); 275 | 276 | nbytes = (bignum_bitcount(out) + 7) / 8; 277 | if((bytes = malloc(4 + 7 + 4 + nbytes)) == NULL) 278 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 279 | PUT_32BIT_MSB_FIRST(bytes, 7); 280 | memcpy(bytes + 4, "ssh-rsa", 7); 281 | PUT_32BIT_MSB_FIRST(bytes + 4 + 7, nbytes); 282 | for (i = 0; i < nbytes; i++) 283 | bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i); 284 | freebn(out); 285 | 286 | *siglen = 4 + 7 + 4 + nbytes; 287 | return bytes; 288 | } 289 | 290 | const struct ssh_signkey ssh_rsa = { 291 | rsa2_public_blob, 292 | rsa2_createkey, 293 | rsa2_sign, 294 | "ssh-rsa", 295 | }; 296 | -------------------------------------------------------------------------------- /sshsh256.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SHA-256 algorithm as described at 3 | * 4 | * http://csrc.nist.gov/cryptval/shs.html 5 | */ 6 | 7 | #include "sshsha.h" 8 | #include "macros.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* ---------------------------------------------------------------------- 17 | * Core SHA256 algorithm: processes 16-word blocks into a message digest. 18 | */ 19 | 20 | #define ror(x,y) ( ((x) << (32-y)) | (((uint32)(x)) >> (y)) ) 21 | #define shr(x,y) ( (((uint32)(x)) >> (y)) ) 22 | #define Ch(x,y,z) ( ((x) & (y)) ^ (~(x) & (z)) ) 23 | #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) 24 | #define bigsigma0(x) ( ror((x),2) ^ ror((x),13) ^ ror((x),22) ) 25 | #define bigsigma1(x) ( ror((x),6) ^ ror((x),11) ^ ror((x),25) ) 26 | #define smallsigma0(x) ( ror((x),7) ^ ror((x),18) ^ shr((x),3) ) 27 | #define smallsigma1(x) ( ror((x),17) ^ ror((x),19) ^ shr((x),10) ) 28 | 29 | void SHA256_Core_Init(SHA256_State *s) { 30 | s->h[0] = 0x6a09e667; 31 | s->h[1] = 0xbb67ae85; 32 | s->h[2] = 0x3c6ef372; 33 | s->h[3] = 0xa54ff53a; 34 | s->h[4] = 0x510e527f; 35 | s->h[5] = 0x9b05688c; 36 | s->h[6] = 0x1f83d9ab; 37 | s->h[7] = 0x5be0cd19; 38 | } 39 | 40 | void SHA256_Block(SHA256_State *s, uint32 *block) { 41 | uint32 w[80]; 42 | uint32 a,b,c,d,e,f,g,h; 43 | static const unsigned long k[] = { 44 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 45 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 46 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 47 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 48 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 49 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 50 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 51 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 52 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 53 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 54 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 55 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 56 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 57 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 58 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 59 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, 60 | }; 61 | 62 | unsigned short t; 63 | 64 | for (t = 0; t < 16; t++) 65 | w[t] = block[t]; 66 | 67 | for (t = 16; t < 64; t++) 68 | w[t] = smallsigma1(w[t-2]) + w[t-7] + smallsigma0(w[t-15]) + w[t-16]; 69 | 70 | a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3]; 71 | e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7]; 72 | 73 | for (t = 0; t < 64; t+=8) { 74 | uint32 t1, t2; 75 | 76 | #define ROUND(j,a,b,c,d,e,f,g,h) \ 77 | t1 = h + bigsigma1(e) + Ch(e,f,g) + k[j] + w[j]; \ 78 | t2 = bigsigma0(a) + Maj(a,b,c); \ 79 | d = d + t1; h = t1 + t2; 80 | 81 | ROUND(t+0, a,b,c,d,e,f,g,h); 82 | ROUND(t+1, h,a,b,c,d,e,f,g); 83 | ROUND(t+2, g,h,a,b,c,d,e,f); 84 | ROUND(t+3, f,g,h,a,b,c,d,e); 85 | ROUND(t+4, e,f,g,h,a,b,c,d); 86 | ROUND(t+5, d,e,f,g,h,a,b,c); 87 | ROUND(t+6, c,d,e,f,g,h,a,b); 88 | ROUND(t+7, b,c,d,e,f,g,h,a); 89 | } 90 | 91 | s->h[0] += a; s->h[1] += b; s->h[2] += c; s->h[3] += d; 92 | s->h[4] += e; s->h[5] += f; s->h[6] += g; s->h[7] += h; 93 | } 94 | 95 | /* ---------------------------------------------------------------------- 96 | * Outer SHA256 algorithm: take an arbitrary length byte string, 97 | * convert it into 16-word blocks with the prescribed padding at 98 | * the end, and pass those blocks to the core SHA256 algorithm. 99 | */ 100 | 101 | #define BLKSIZE 64 102 | 103 | void SHA256_Init(SHA256_State *s) { 104 | SHA256_Core_Init(s); 105 | s->blkused = 0; 106 | s->lenhi = s->lenlo = 0; 107 | } 108 | 109 | void SHA256_Bytes(SHA256_State *s, const void *p, short len) { 110 | unsigned char *q = (unsigned char *)p; 111 | uint32 wordblock[16]; 112 | uint32 lenw = len; 113 | short i; 114 | 115 | /* 116 | * Update the length field. 117 | */ 118 | s->lenlo += lenw; 119 | s->lenhi += (s->lenlo < lenw); 120 | 121 | if (s->blkused && s->blkused+len < BLKSIZE) { 122 | /* 123 | * Trivial case: just add to the block. 124 | */ 125 | memcpy(s->block + s->blkused, q, len); 126 | s->blkused += len; 127 | } else { 128 | /* 129 | * We must complete and process at least one block. 130 | */ 131 | while (s->blkused + len >= BLKSIZE) { 132 | memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused); 133 | q += BLKSIZE - s->blkused; 134 | len -= BLKSIZE - s->blkused; 135 | /* Now process the block. Gather bytes big-endian into words */ 136 | for (i = 0; i < 16; i++) { 137 | wordblock[i] = 138 | ( ((uint32)s->block[i*4+0]) << 24 ) | 139 | ( ((uint32)s->block[i*4+1]) << 16 ) | 140 | ( ((uint32)s->block[i*4+2]) << 8 ) | 141 | ( ((uint32)s->block[i*4+3]) << 0 ); 142 | } 143 | SHA256_Block(s, wordblock); 144 | s->blkused = 0; 145 | } 146 | memcpy(s->block, q, len); 147 | s->blkused = len; 148 | } 149 | } 150 | 151 | void SHA256_Final(SHA256_State *s, unsigned char *digest) { 152 | short i; 153 | short pad; 154 | unsigned char c[64]; 155 | uint32 lenhi, lenlo; 156 | 157 | if (s->blkused >= 56) 158 | pad = 56 + 64 - s->blkused; 159 | else 160 | pad = 56 - s->blkused; 161 | 162 | lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3)); 163 | lenlo = (s->lenlo << 3); 164 | 165 | memset(c, 0, pad); 166 | c[0] = 0x80; 167 | SHA256_Bytes(s, &c, pad); 168 | 169 | c[0] = (lenhi >> 24) & 0xFF; 170 | c[1] = (lenhi >> 16) & 0xFF; 171 | c[2] = (lenhi >> 8) & 0xFF; 172 | c[3] = (lenhi >> 0) & 0xFF; 173 | c[4] = (lenlo >> 24) & 0xFF; 174 | c[5] = (lenlo >> 16) & 0xFF; 175 | c[6] = (lenlo >> 8) & 0xFF; 176 | c[7] = (lenlo >> 0) & 0xFF; 177 | 178 | SHA256_Bytes(s, &c, 8); 179 | 180 | for (i = 0; i < 8; i++) { 181 | digest[i*4+0] = (s->h[i] >> 24) & 0xFF; 182 | digest[i*4+1] = (s->h[i] >> 16) & 0xFF; 183 | digest[i*4+2] = (s->h[i] >> 8) & 0xFF; 184 | digest[i*4+3] = (s->h[i] >> 0) & 0xFF; 185 | } 186 | } 187 | 188 | void SHA256_Simple(const void *p, int len, unsigned char *output) { 189 | SHA256_State s; 190 | 191 | SHA256_Init(&s); 192 | SHA256_Bytes(&s, p, len); 193 | SHA256_Final(&s, output); 194 | memset(&s, 0, sizeof(s)); 195 | } 196 | 197 | void sha256_string(SHA256_State * s, void *str, unsigned long len) 198 | { 199 | unsigned char lenblk[4]; 200 | 201 | PUT_32BIT_MSB_FIRST(lenblk, len); 202 | SHA256_Bytes(s, lenblk, 4); 203 | SHA256_Bytes(s, str, len); 204 | } 205 | 206 | 207 | void sha256_mpint(SHA256_State * s, Bignum b) 208 | { 209 | unsigned char *p; 210 | unsigned long len; 211 | 212 | p = ssh2_mpint_fmt(b, &len); 213 | sha256_string(s, p, len); 214 | free(p); 215 | } 216 | 217 | static SHA256_State sha256_cs_mac_s1, sha256_cs_mac_s2; 218 | static SHA256_State sha256_sc_mac_s1, sha256_sc_mac_s2; 219 | 220 | static void sha256_key(SHA256_State * s1, SHA256_State * s2, 221 | unsigned char *key, unsigned short len) 222 | { 223 | unsigned char foo[64]; 224 | unsigned short i; 225 | 226 | memset(foo, 0x36, 64); 227 | for (i = 0; i < len && i < 64; i++) 228 | foo[i] ^= key[i]; 229 | SHA256_Init(s1); 230 | SHA256_Bytes(s1, foo, 64); 231 | 232 | memset(foo, 0x5C, 64); 233 | for (i = 0; i < len && i < 64; i++) 234 | foo[i] ^= key[i]; 235 | SHA256_Init(s2); 236 | SHA256_Bytes(s2, foo, 64); 237 | 238 | memset(foo, 0, 64); /* burn the evidence */ 239 | } 240 | 241 | void sha256_cskey(unsigned char *key) 242 | { 243 | sha256_key(&sha256_cs_mac_s1, &sha256_cs_mac_s2, key, 32); 244 | } 245 | 246 | void sha256_sckey(unsigned char *key) 247 | { 248 | sha256_key(&sha256_sc_mac_s1, &sha256_sc_mac_s2, key, 32); 249 | } 250 | 251 | static void sha256_do_hmac(SHA256_State * s1, SHA256_State * s2, 252 | unsigned char *blk, unsigned short len, unsigned long seq, 253 | unsigned char *hmac) 254 | { 255 | SHA256_State s; 256 | unsigned char intermediate[32]; 257 | 258 | intermediate[0] = (unsigned char) ((seq >> 24) & 0xFF); 259 | intermediate[1] = (unsigned char) ((seq >> 16) & 0xFF); 260 | intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF); 261 | intermediate[3] = (unsigned char) ((seq) & 0xFF); 262 | 263 | s = *s1; /* structure copy */ 264 | SHA256_Bytes(&s, intermediate, 4); 265 | SHA256_Bytes(&s, blk, len); 266 | SHA256_Final(&s, intermediate); 267 | s = *s2; /* structure copy */ 268 | SHA256_Bytes(&s, intermediate, 32); 269 | SHA256_Final(&s, hmac); 270 | } 271 | 272 | void sha256_generate(unsigned char *blk, unsigned short len, unsigned long seq) 273 | { 274 | sha256_do_hmac(&sha256_cs_mac_s1, &sha256_cs_mac_s2, blk, len, seq, blk + len); 275 | } 276 | 277 | int sha256_verify(unsigned char *blk, unsigned short len, unsigned long seq) 278 | { 279 | unsigned char correct[32]; 280 | sha256_do_hmac(&sha256_sc_mac_s1, &sha256_sc_mac_s2, blk, len, seq, correct); 281 | return !memcmp(correct, blk + len, 32); 282 | } 283 | -------------------------------------------------------------------------------- /sshsh512.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SHA-512 algorithm as described at 3 | * 4 | * http://csrc.nist.gov/cryptval/shs.html 5 | * 6 | * Taken from the PuTTY source. 7 | */ 8 | 9 | #include 10 | 11 | #include "sshsha.h" 12 | 13 | #define BLKSIZE 128 14 | 15 | /* 16 | * Arithmetic implementations. Note that AND, XOR and NOT can 17 | * overlap destination with one source, but the others can't. 18 | */ 19 | #define add(r,x,y) ( r.lo = y.lo + x.lo, \ 20 | r.hi = y.hi + x.hi + (r.lo < y.lo) ) 21 | #define rorB(r,x,y) ( r.lo = (x.hi >> ((y)-32)) | (x.lo << (64-(y))), \ 22 | r.hi = (x.lo >> ((y)-32)) | (x.hi << (64-(y))) ) 23 | #define rorL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \ 24 | r.hi = (x.hi >> (y)) | (x.lo << (32-(y))) ) 25 | #define shrB(r,x,y) ( r.lo = x.hi >> ((y)-32), r.hi = 0 ) 26 | #define shrL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \ 27 | r.hi = x.hi >> (y) ) 28 | #define and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi ) 29 | #define xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi ) 30 | #define not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi ) 31 | #define INIT(h,l) { h, l } 32 | #define BUILD(r,h,l) ( r.hi = h, r.lo = l ) 33 | #define EXTRACT(h,l,r) ( h = r.hi, l = r.lo ) 34 | 35 | /* ---------------------------------------------------------------------- 36 | * Core SHA512 algorithm: processes 16-doubleword blocks into a 37 | * message digest. 38 | */ 39 | 40 | #define Ch(r,t,x,y,z) ( not(t,x), and(r,t,z), and(t,x,y), xor(r,r,t) ) 41 | #define Maj(r,t,x,y,z) ( and(r,x,y), and(t,x,z), xor(r,r,t), \ 42 | and(t,y,z), xor(r,r,t) ) 43 | #define bigsigma0(r,t,x) ( rorL(r,x,28), rorB(t,x,34), xor(r,r,t), \ 44 | rorB(t,x,39), xor(r,r,t) ) 45 | #define bigsigma1(r,t,x) ( rorL(r,x,14), rorL(t,x,18), xor(r,r,t), \ 46 | rorB(t,x,41), xor(r,r,t) ) 47 | #define smallsigma0(r,t,x) ( rorL(r,x,1), rorL(t,x,8), xor(r,r,t), \ 48 | shrL(t,x,7), xor(r,r,t) ) 49 | #define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), xor(r,r,t), \ 50 | shrL(t,x,6), xor(r,r,t) ) 51 | 52 | void SHA512_Core_Init(SHA512_State *s) { 53 | static const uint64 iv[] = { 54 | INIT(0x6a09e667, 0xf3bcc908), 55 | INIT(0xbb67ae85, 0x84caa73b), 56 | INIT(0x3c6ef372, 0xfe94f82b), 57 | INIT(0xa54ff53a, 0x5f1d36f1), 58 | INIT(0x510e527f, 0xade682d1), 59 | INIT(0x9b05688c, 0x2b3e6c1f), 60 | INIT(0x1f83d9ab, 0xfb41bd6b), 61 | INIT(0x5be0cd19, 0x137e2179), 62 | }; 63 | int i; 64 | for (i = 0; i < 8; i++) 65 | s->h[i] = iv[i]; 66 | } 67 | 68 | void SHA512_Block(SHA512_State *s, uint64 *block) { 69 | uint64 w[80]; 70 | uint64 a,b,c,d,e,f,g,h; 71 | static const uint64 k[] = { 72 | INIT(0x428a2f98, 0xd728ae22), INIT(0x71374491, 0x23ef65cd), 73 | INIT(0xb5c0fbcf, 0xec4d3b2f), INIT(0xe9b5dba5, 0x8189dbbc), 74 | INIT(0x3956c25b, 0xf348b538), INIT(0x59f111f1, 0xb605d019), 75 | INIT(0x923f82a4, 0xaf194f9b), INIT(0xab1c5ed5, 0xda6d8118), 76 | INIT(0xd807aa98, 0xa3030242), INIT(0x12835b01, 0x45706fbe), 77 | INIT(0x243185be, 0x4ee4b28c), INIT(0x550c7dc3, 0xd5ffb4e2), 78 | INIT(0x72be5d74, 0xf27b896f), INIT(0x80deb1fe, 0x3b1696b1), 79 | INIT(0x9bdc06a7, 0x25c71235), INIT(0xc19bf174, 0xcf692694), 80 | INIT(0xe49b69c1, 0x9ef14ad2), INIT(0xefbe4786, 0x384f25e3), 81 | INIT(0x0fc19dc6, 0x8b8cd5b5), INIT(0x240ca1cc, 0x77ac9c65), 82 | INIT(0x2de92c6f, 0x592b0275), INIT(0x4a7484aa, 0x6ea6e483), 83 | INIT(0x5cb0a9dc, 0xbd41fbd4), INIT(0x76f988da, 0x831153b5), 84 | INIT(0x983e5152, 0xee66dfab), INIT(0xa831c66d, 0x2db43210), 85 | INIT(0xb00327c8, 0x98fb213f), INIT(0xbf597fc7, 0xbeef0ee4), 86 | INIT(0xc6e00bf3, 0x3da88fc2), INIT(0xd5a79147, 0x930aa725), 87 | INIT(0x06ca6351, 0xe003826f), INIT(0x14292967, 0x0a0e6e70), 88 | INIT(0x27b70a85, 0x46d22ffc), INIT(0x2e1b2138, 0x5c26c926), 89 | INIT(0x4d2c6dfc, 0x5ac42aed), INIT(0x53380d13, 0x9d95b3df), 90 | INIT(0x650a7354, 0x8baf63de), INIT(0x766a0abb, 0x3c77b2a8), 91 | INIT(0x81c2c92e, 0x47edaee6), INIT(0x92722c85, 0x1482353b), 92 | INIT(0xa2bfe8a1, 0x4cf10364), INIT(0xa81a664b, 0xbc423001), 93 | INIT(0xc24b8b70, 0xd0f89791), INIT(0xc76c51a3, 0x0654be30), 94 | INIT(0xd192e819, 0xd6ef5218), INIT(0xd6990624, 0x5565a910), 95 | INIT(0xf40e3585, 0x5771202a), INIT(0x106aa070, 0x32bbd1b8), 96 | INIT(0x19a4c116, 0xb8d2d0c8), INIT(0x1e376c08, 0x5141ab53), 97 | INIT(0x2748774c, 0xdf8eeb99), INIT(0x34b0bcb5, 0xe19b48a8), 98 | INIT(0x391c0cb3, 0xc5c95a63), INIT(0x4ed8aa4a, 0xe3418acb), 99 | INIT(0x5b9cca4f, 0x7763e373), INIT(0x682e6ff3, 0xd6b2b8a3), 100 | INIT(0x748f82ee, 0x5defb2fc), INIT(0x78a5636f, 0x43172f60), 101 | INIT(0x84c87814, 0xa1f0ab72), INIT(0x8cc70208, 0x1a6439ec), 102 | INIT(0x90befffa, 0x23631e28), INIT(0xa4506ceb, 0xde82bde9), 103 | INIT(0xbef9a3f7, 0xb2c67915), INIT(0xc67178f2, 0xe372532b), 104 | INIT(0xca273ece, 0xea26619c), INIT(0xd186b8c7, 0x21c0c207), 105 | INIT(0xeada7dd6, 0xcde0eb1e), INIT(0xf57d4f7f, 0xee6ed178), 106 | INIT(0x06f067aa, 0x72176fba), INIT(0x0a637dc5, 0xa2c898a6), 107 | INIT(0x113f9804, 0xbef90dae), INIT(0x1b710b35, 0x131c471b), 108 | INIT(0x28db77f5, 0x23047d84), INIT(0x32caab7b, 0x40c72493), 109 | INIT(0x3c9ebe0a, 0x15c9bebc), INIT(0x431d67c4, 0x9c100d4c), 110 | INIT(0x4cc5d4be, 0xcb3e42b6), INIT(0x597f299c, 0xfc657e2a), 111 | INIT(0x5fcb6fab, 0x3ad6faec), INIT(0x6c44198c, 0x4a475817), 112 | }; 113 | 114 | int t; 115 | 116 | for (t = 0; t < 16; t++) 117 | w[t] = block[t]; 118 | 119 | for (t = 16; t < 80; t++) { 120 | uint64 p, q, r, tmp; 121 | smallsigma1(p, tmp, w[t-2]); 122 | smallsigma0(q, tmp, w[t-15]); 123 | add(r, p, q); 124 | add(p, r, w[t-7]); 125 | add(w[t], p, w[t-16]); 126 | } 127 | 128 | a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3]; 129 | e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7]; 130 | 131 | for (t = 0; t < 80; t+=8) { 132 | uint64 tmp, p, q, r; 133 | 134 | #define ROUND(j,a,b,c,d,e,f,g,h) \ 135 | bigsigma1(p, tmp, e); \ 136 | Ch(q, tmp, e, f, g); \ 137 | add(r, p, q); \ 138 | add(p, r, k[j]) ; \ 139 | add(q, p, w[j]); \ 140 | add(r, q, h); \ 141 | bigsigma0(p, tmp, a); \ 142 | Maj(tmp, q, a, b, c); \ 143 | add(q, tmp, p); \ 144 | add(p, r, d); \ 145 | d = p; \ 146 | add(h, q, r); 147 | 148 | ROUND(t+0, a,b,c,d,e,f,g,h); 149 | ROUND(t+1, h,a,b,c,d,e,f,g); 150 | ROUND(t+2, g,h,a,b,c,d,e,f); 151 | ROUND(t+3, f,g,h,a,b,c,d,e); 152 | ROUND(t+4, e,f,g,h,a,b,c,d); 153 | ROUND(t+5, d,e,f,g,h,a,b,c); 154 | ROUND(t+6, c,d,e,f,g,h,a,b); 155 | ROUND(t+7, b,c,d,e,f,g,h,a); 156 | } 157 | 158 | { 159 | uint64 tmp; 160 | #define UPDATE(state, local) ( tmp = state, add(state, tmp, local) ) 161 | UPDATE(s->h[0], a); UPDATE(s->h[1], b); 162 | UPDATE(s->h[2], c); UPDATE(s->h[3], d); 163 | UPDATE(s->h[4], e); UPDATE(s->h[5], f); 164 | UPDATE(s->h[6], g); UPDATE(s->h[7], h); 165 | } 166 | } 167 | 168 | /* ---------------------------------------------------------------------- 169 | * Outer SHA512 algorithm: take an arbitrary length byte string, 170 | * convert it into 16-doubleword blocks with the prescribed padding 171 | * at the end, and pass those blocks to the core SHA512 algorithm. 172 | */ 173 | 174 | void SHA512_Init(SHA512_State *s) { 175 | int i; 176 | SHA512_Core_Init(s); 177 | s->blkused = 0; 178 | for (i = 0; i < 4; i++) 179 | s->len[i] = 0; 180 | } 181 | 182 | void SHA512_Bytes(SHA512_State *s, const void *p, int len) { 183 | unsigned char *q = (unsigned char *)p; 184 | uint64 wordblock[16]; 185 | uint32 lenw = len; 186 | int i; 187 | 188 | /* 189 | * Update the length field. 190 | */ 191 | for (i = 0; i < 4; i++) { 192 | s->len[i] += lenw; 193 | lenw = (s->len[i] < lenw); 194 | } 195 | 196 | if (s->blkused && s->blkused+len < BLKSIZE) { 197 | /* 198 | * Trivial case: just add to the block. 199 | */ 200 | memcpy(s->block + s->blkused, q, len); 201 | s->blkused += len; 202 | } else { 203 | /* 204 | * We must complete and process at least one block. 205 | */ 206 | while (s->blkused + len >= BLKSIZE) { 207 | memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused); 208 | q += BLKSIZE - s->blkused; 209 | len -= BLKSIZE - s->blkused; 210 | /* Now process the block. Gather bytes big-endian into words */ 211 | for (i = 0; i < 16; i++) { 212 | uint32 h, l; 213 | h = ( ((uint32)s->block[i*8+0]) << 24 ) | 214 | ( ((uint32)s->block[i*8+1]) << 16 ) | 215 | ( ((uint32)s->block[i*8+2]) << 8 ) | 216 | ( ((uint32)s->block[i*8+3]) << 0 ); 217 | l = ( ((uint32)s->block[i*8+4]) << 24 ) | 218 | ( ((uint32)s->block[i*8+5]) << 16 ) | 219 | ( ((uint32)s->block[i*8+6]) << 8 ) | 220 | ( ((uint32)s->block[i*8+7]) << 0 ); 221 | BUILD(wordblock[i], h, l); 222 | } 223 | SHA512_Block(s, wordblock); 224 | s->blkused = 0; 225 | } 226 | memcpy(s->block, q, len); 227 | s->blkused = len; 228 | } 229 | } 230 | 231 | void SHA512_Final(SHA512_State *s, unsigned char *digest) { 232 | int i; 233 | int pad; 234 | unsigned char c[BLKSIZE]; 235 | uint32 len[4]; 236 | 237 | if (s->blkused >= BLKSIZE-16) 238 | pad = (BLKSIZE-16) + BLKSIZE - s->blkused; 239 | else 240 | pad = (BLKSIZE-16) - s->blkused; 241 | 242 | for (i = 4; i-- ;) { 243 | uint32 lenhi = s->len[i]; 244 | uint32 lenlo = i > 0 ? s->len[i-1] : 0; 245 | len[i] = (lenhi << 3) | (lenlo >> (32-3)); 246 | } 247 | 248 | memset(c, 0, pad); 249 | c[0] = 0x80; 250 | SHA512_Bytes(s, &c, pad); 251 | 252 | for (i = 0; i < 4; i++) { 253 | c[i*4+0] = (len[3-i] >> 24) & 0xFF; 254 | c[i*4+1] = (len[3-i] >> 16) & 0xFF; 255 | c[i*4+2] = (len[3-i] >> 8) & 0xFF; 256 | c[i*4+3] = (len[3-i] >> 0) & 0xFF; 257 | } 258 | 259 | SHA512_Bytes(s, &c, 16); 260 | 261 | for (i = 0; i < 8; i++) { 262 | uint32 h, l; 263 | EXTRACT(h, l, s->h[i]); 264 | digest[i*8+0] = (h >> 24) & 0xFF; 265 | digest[i*8+1] = (h >> 16) & 0xFF; 266 | digest[i*8+2] = (h >> 8) & 0xFF; 267 | digest[i*8+3] = (h >> 0) & 0xFF; 268 | digest[i*8+4] = (l >> 24) & 0xFF; 269 | digest[i*8+5] = (l >> 16) & 0xFF; 270 | digest[i*8+6] = (l >> 8) & 0xFF; 271 | digest[i*8+7] = (l >> 0) & 0xFF; 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /sshsha.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SHA1 hash algorithm. Used in SSH2 as a MAC, and the transform is 3 | * also used as a `stirring' function for the PuTTY random number 4 | * pool. Implemented directly from the specification by Simon 5 | * Tatham. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "sshsha.h" 12 | #include "macros.h" 13 | #include "common.h" 14 | #if defined (MEMWATCH) 15 | #include "memwatch.h" 16 | #endif 17 | 18 | unsigned char *ssh2_mpint_fmt(Bignum b, unsigned long *len) 19 | { 20 | unsigned char *p; 21 | unsigned short i, n; 22 | 23 | n = (bignum_bitcount(b) + 7) / 8; 24 | if((p = (unsigned char *) malloc((n + 1) * sizeof(char))) == NULL) 25 | fatal("Memory allocation error. %s: %d", __FILE__, __LINE__); 26 | p[0] = 0; 27 | for (i = 1; i <= n; i++) 28 | p[i] = bignum_byte(b, n - i); 29 | i = 0; 30 | while (i <= n && p[i] == 0 && (p[i + 1] & 0x80) == 0) 31 | i++; 32 | memmove(p, p + i, n + 1 - i); 33 | *len = n + 1 - i; 34 | return p; 35 | } 36 | 37 | void sha_string(SHA_State * s, void *str, unsigned long len) 38 | { 39 | unsigned char lenblk[4]; 40 | 41 | PUT_32BIT_MSB_FIRST(lenblk, len); 42 | SHA_Bytes(s, lenblk, 4); 43 | SHA_Bytes(s, str, len); 44 | } 45 | 46 | 47 | void sha_mpint(SHA_State * s, Bignum b) 48 | { 49 | unsigned char *p; 50 | unsigned long len; 51 | 52 | p = ssh2_mpint_fmt(b, &len); 53 | sha_string(s, p, len); 54 | free(p); 55 | } 56 | 57 | 58 | /* ---------------------------------------------------------------------- 59 | * Core SHA algorithm: processes 16-word blocks into a message digest. 60 | */ 61 | 62 | #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) ) 63 | 64 | void SHA_Core_Init(uint32 h[5]) 65 | { 66 | h[0] = 0x67452301; 67 | h[1] = 0xefcdab89; 68 | h[2] = 0x98badcfe; 69 | h[3] = 0x10325476; 70 | h[4] = 0xc3d2e1f0; 71 | } 72 | 73 | void SHATransform(word32 * digest, word32 * block) 74 | { 75 | word32 w[80]; 76 | word32 a, b, c, d, e; 77 | unsigned short t; 78 | 79 | for (t = 0; t < 16; t++) 80 | w[t] = block[t]; 81 | 82 | for (t = 16; t < 80; t++) { 83 | word32 tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]; 84 | w[t] = rol(tmp, 1); 85 | } 86 | 87 | a = digest[0]; 88 | b = digest[1]; 89 | c = digest[2]; 90 | d = digest[3]; 91 | e = digest[4]; 92 | 93 | for (t = 0; t < 20; t++) { 94 | word32 tmp = 95 | rol(a, 5) + ((b & c) | (d & ~b)) + e + w[t] + 0x5a827999; 96 | e = d; 97 | d = c; 98 | c = rol(b, 30); 99 | b = a; 100 | a = tmp; 101 | } 102 | for (t = 20; t < 40; t++) { 103 | word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1; 104 | e = d; 105 | d = c; 106 | c = rol(b, 30); 107 | b = a; 108 | a = tmp; 109 | } 110 | for (t = 40; t < 60; t++) { 111 | word32 tmp = rol(a, 112 | 5) + ((b & c) | (b & d) | (c & d)) + e + w[t] + 113 | 0x8f1bbcdc; 114 | e = d; 115 | d = c; 116 | c = rol(b, 30); 117 | b = a; 118 | a = tmp; 119 | } 120 | for (t = 60; t < 80; t++) { 121 | word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6; 122 | e = d; 123 | d = c; 124 | c = rol(b, 30); 125 | b = a; 126 | a = tmp; 127 | } 128 | 129 | digest[0] += a; 130 | digest[1] += b; 131 | digest[2] += c; 132 | digest[3] += d; 133 | digest[4] += e; 134 | } 135 | 136 | /* ---------------------------------------------------------------------- 137 | * Outer SHA algorithm: take an arbitrary length byte string, 138 | * convert it into 16-word blocks with the prescribed padding at 139 | * the end, and pass those blocks to the core SHA algorithm. 140 | */ 141 | 142 | void SHA_Init(SHA_State * s) 143 | { 144 | SHA_Core_Init(s->h); 145 | s->blkused = 0; 146 | s->lenhi = s->lenlo = 0; 147 | } 148 | 149 | void SHA_Bytes(SHA_State * s, void *p, short len) 150 | { 151 | unsigned char *q = (unsigned char *) p; 152 | uint32 wordblock[16]; 153 | uint32 lenw = len; 154 | unsigned short i; 155 | 156 | /* 157 | * Update the length field. 158 | */ 159 | s->lenlo += lenw; 160 | s->lenhi += (s->lenlo < lenw); 161 | 162 | if (s->blkused && s->blkused + len < 64) { 163 | /* 164 | * Trivial case: just add to the block. 165 | */ 166 | memcpy(s->block + s->blkused, q, len); 167 | s->blkused += len; 168 | } else { 169 | /* 170 | * We must complete and process at least one block. 171 | */ 172 | while (s->blkused + len >= 64) { 173 | memcpy(s->block + s->blkused, q, 64 - s->blkused); 174 | q += 64 - s->blkused; 175 | len -= 64 - s->blkused; 176 | /* Now process the block. Gather bytes big-endian into words */ 177 | for (i = 0; i < 16; i++) { 178 | wordblock[i] = 179 | (((uint32) s->block[i * 4 + 0]) << 24) | 180 | (((uint32) s->block[i * 4 + 1]) << 16) | 181 | (((uint32) s->block[i * 4 + 2]) << 8) | 182 | (((uint32) s->block[i * 4 + 3]) << 0); 183 | } 184 | SHATransform(s->h, wordblock); 185 | s->blkused = 0; 186 | } 187 | memcpy(s->block, q, len); 188 | s->blkused = len; 189 | } 190 | } 191 | 192 | void SHA_Final(SHA_State * s, unsigned char *output) 193 | { 194 | unsigned short i, pad; 195 | unsigned char c[64]; 196 | uint32 lenhi, lenlo; 197 | 198 | if (s->blkused >= 56) 199 | pad = 56 + 64 - s->blkused; 200 | else 201 | pad = 56 - s->blkused; 202 | 203 | lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3)); 204 | lenlo = (s->lenlo << 3); 205 | 206 | memset(c, 0, pad); 207 | c[0] = 0x80; 208 | SHA_Bytes(s, &c, pad); 209 | 210 | c[0] = (lenhi >> 24) & 0xFF; 211 | c[1] = (lenhi >> 16) & 0xFF; 212 | c[2] = (lenhi >> 8) & 0xFF; 213 | c[3] = (lenhi >> 0) & 0xFF; 214 | c[4] = (lenlo >> 24) & 0xFF; 215 | c[5] = (lenlo >> 16) & 0xFF; 216 | c[6] = (lenlo >> 8) & 0xFF; 217 | c[7] = (lenlo >> 0) & 0xFF; 218 | 219 | SHA_Bytes(s, &c, 8); 220 | 221 | for (i = 0; i < 5; i++) { 222 | output[i * 4] = (s->h[i] >> 24) & 0xFF; 223 | output[i * 4 + 1] = (s->h[i] >> 16) & 0xFF; 224 | output[i * 4 + 2] = (s->h[i] >> 8) & 0xFF; 225 | output[i * 4 + 3] = (s->h[i]) & 0xFF; 226 | } 227 | } 228 | 229 | /* ---------------------------------------------------------------------- 230 | * The above is the SHA-1 algorithm itself. Now we implement the 231 | * HMAC wrapper on it. 232 | */ 233 | 234 | static SHA_State sha1_cs_mac_s1, sha1_cs_mac_s2; 235 | static SHA_State sha1_sc_mac_s1, sha1_sc_mac_s2; 236 | 237 | static void sha1_key(SHA_State * s1, SHA_State * s2, 238 | unsigned char *key, unsigned short len) 239 | { 240 | unsigned char foo[64]; 241 | unsigned short i; 242 | 243 | memset(foo, 0x36, 64); 244 | for (i = 0; i < len && i < 64; i++) 245 | foo[i] ^= key[i]; 246 | SHA_Init(s1); 247 | SHA_Bytes(s1, foo, 64); 248 | 249 | memset(foo, 0x5C, 64); 250 | for (i = 0; i < len && i < 64; i++) 251 | foo[i] ^= key[i]; 252 | SHA_Init(s2); 253 | SHA_Bytes(s2, foo, 64); 254 | 255 | memset(foo, 0, 64); /* burn the evidence */ 256 | } 257 | 258 | void sha1_cskey(unsigned char *key) 259 | { 260 | sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 20); 261 | } 262 | 263 | void sha1_sckey(unsigned char *key) 264 | { 265 | sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 20); 266 | } 267 | 268 | static void sha1_do_hmac(SHA_State * s1, SHA_State * s2, 269 | unsigned char *blk, unsigned short len, unsigned long seq, 270 | unsigned char *hmac) 271 | { 272 | SHA_State s; 273 | unsigned char intermediate[20]; 274 | 275 | intermediate[0] = (unsigned char) ((seq >> 24) & 0xFF); 276 | intermediate[1] = (unsigned char) ((seq >> 16) & 0xFF); 277 | intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF); 278 | intermediate[3] = (unsigned char) ((seq) & 0xFF); 279 | 280 | s = *s1; /* structure copy */ 281 | SHA_Bytes(&s, intermediate, 4); 282 | SHA_Bytes(&s, blk, len); 283 | SHA_Final(&s, intermediate); 284 | s = *s2; /* structure copy */ 285 | SHA_Bytes(&s, intermediate, 20); 286 | SHA_Final(&s, hmac); 287 | } 288 | 289 | void sha1_generate(unsigned char *blk, unsigned short len, unsigned long seq) 290 | { 291 | sha1_do_hmac(&sha1_cs_mac_s1, &sha1_cs_mac_s2, blk, len, seq, 292 | blk + len); 293 | } 294 | 295 | int sha1_verify(unsigned char *blk, unsigned short len, unsigned long seq) 296 | { 297 | unsigned char correct[20]; 298 | sha1_do_hmac(&sha1_sc_mac_s1, &sha1_sc_mac_s2, blk, len, seq, correct); 299 | return !memcmp(correct, blk + len, 20); 300 | } 301 | 302 | void SHA_Simple(void *p, int len, unsigned char *output) 303 | { 304 | SHA_State s; 305 | 306 | SHA_Init(&s); 307 | SHA_Bytes(&s, p, len); 308 | SHA_Final(&s, output); 309 | } 310 | 311 | void hmac_sha1_simple(void *key, int keylen, void *data, int datalen, 312 | unsigned char *output) { 313 | SHA_State s1, s2; 314 | unsigned char intermediate[20]; 315 | 316 | sha1_key(&s1, &s2, key, keylen); 317 | SHA_Bytes(&s1, data, datalen); 318 | SHA_Final(&s1, intermediate); 319 | 320 | SHA_Bytes(&s2, intermediate, 20); 321 | SHA_Final(&s2, output); 322 | } 323 | -------------------------------------------------------------------------------- /tel386.lnk: -------------------------------------------------------------------------------- 1 | System causeway 2 | Name tel386.exe 3 | Debug all 4 | Option map 5 | File telnet.obj 6 | Library misc.lib,vt100.lib,wattcpwf.lib 7 | -------------------------------------------------------------------------------- /telnet.c: -------------------------------------------------------------------------------- 1 | /* telnet.c Copyright (c) 2000-2003 Nagy Daniel 2 | * 3 | * $Date: 2006/02/23 17:58:29 $ 4 | * $Revision: 1.2 $ 5 | * 6 | * This module is the main part: 7 | * - command line parsing 8 | * - client loop 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; either version 2 13 | * of the License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Library General Public 21 | * License along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "tcp.h" 33 | #include "version.h" 34 | #include "vidio.h" 35 | #include "vttio.h" 36 | #include "keyio.h" 37 | #include "keymap.h" 38 | #include "config.h" 39 | #include "telnet.h" 40 | #include "common.h" 41 | 42 | /* external functions */ 43 | SendFuncPtr SendPacket; 44 | void ChrDelete(void); 45 | 46 | /* external structures, variables */ 47 | extern unsigned short statusline; 48 | extern unsigned columns; /* Columns on logical terminal screen */ 49 | extern unsigned lines; /* Lines on logical terminal screen */ 50 | extern unsigned short vidmode; 51 | 52 | /* global variables */ 53 | Config GlobalConfig; /* global configuration structure */ 54 | unsigned short Configuration = 0; /* Configuration bits */ 55 | 56 | /* local variables */ 57 | struct vidmod{ 58 | char *mode; 59 | unsigned short vidmode; 60 | }; 61 | static struct vidmod modes[]={ {"80x25", 3}, 62 | {"80x60", 0x108}, 63 | {"132x25", 0x109}, 64 | {"132x50", 0x10b} }; 65 | static unsigned char Inbuf[1024]; /* buffer for incoming data */ 66 | static unsigned char Outbuf[1024]; /* buffer for outgoing data */ 67 | static unsigned char echo = 0; /* is the echoing on? */ 68 | static char *RemoteHost = NULL; 69 | static unsigned char *term; 70 | static unsigned short RemotePort = 23; 71 | static FILE *LogFile = NULL; 72 | 73 | /* 74 | * Send Telnet packet 75 | */ 76 | void SendTelnetPacket(char *buff, unsigned short len) 77 | { 78 | if(sock_write(&GlobalConfig.s, buff, len) != len) 79 | fatal("Sock write: %s", strerror(errno)); 80 | } 81 | 82 | /* 83 | * Send Telnet command 84 | */ 85 | static void SendTC(unsigned char c1, unsigned char c2) 86 | { 87 | unsigned char buff[3]; 88 | 89 | buff[0] = IAC; 90 | buff[1] = c1; 91 | buff[2] = c2; 92 | SendPacket(buff, 3); 93 | } 94 | 95 | /* 96 | * Initialize global structures 97 | */ 98 | static void Config_Init(void) 99 | { 100 | memset(Outbuf, 0, sizeof(Outbuf)); 101 | term = "xterm"; /* default is "xterm" */ 102 | SendPacket = SendTelnetPacket; 103 | LogFile = NULL; 104 | GlobalConfig.brailab = NULL; 105 | } 106 | 107 | /* 108 | * Client loop. This runs until Telnet connection is terminated 109 | */ 110 | static short dosession(void) 111 | { 112 | unsigned short n; 113 | unsigned short len; 114 | unsigned char Command, Option, y, s; 115 | unsigned char *ptr; 116 | unsigned char sb[40]; 117 | 118 | while(ConChk()){ /* examine STDIN */ 119 | if(echo) /* If we have remote echo, don't bother much */ 120 | DoKey(); 121 | else{ /* else we have to buffer user input */ 122 | n = strlen(Outbuf); 123 | y = getch(); 124 | if(!y){ /* we have a special character here? */ 125 | y = getch(); 126 | s = _bios_keybrd(_KEYBRD_SHIFTSTATUS) & 3; /* shift state */ 127 | if(y == 0x2D) /* ALT-X ? */ 128 | fatal("Terminating session"); 129 | else if(y == 0x49 && s){ /* shift+pgup */ 130 | SbkBack(); 131 | break; 132 | } else if(y == 0x51 && s){ 133 | SbkForward(); 134 | break; 135 | } else 136 | break; 137 | } 138 | SbkSetPage(-1); 139 | ConOut(y); /* echo to screen */ 140 | switch(y){ 141 | case 8: /* backspace */ 142 | if(n > 0) 143 | Outbuf[n-1] = 0; 144 | ChrDelete(); 145 | break; 146 | 147 | case('\r'): /* return */ 148 | ConOut('\n'); 149 | strcat(Outbuf, "\n"); 150 | SendPacket(Outbuf, strlen(Outbuf)); 151 | memset(Outbuf, 0, strlen(Outbuf)); 152 | break; 153 | 154 | default: 155 | strncat(Outbuf, &y, 1); 156 | break; 157 | } /* switch */ 158 | } /* else */ 159 | } /* while */ 160 | 161 | if(!tcp_tick(&GlobalConfig.s)){ /* TCP wait */ 162 | puts("Connection closed"); 163 | return(EXIT_TELNET); 164 | } 165 | 166 | if(!sock_dataready(&GlobalConfig.s)) 167 | return(0); /* Begin loop again if none */ 168 | 169 | SbkSetPage(-1); 170 | 171 | len = sock_fastread(&GlobalConfig.s, Inbuf, 1024); 172 | 173 | for(ptr = Inbuf; len > 0; len--){ 174 | if(*ptr != IAC){ /* isn't it a Telnet command? */ 175 | ConOut(*ptr); 176 | if(LogFile) 177 | fputc(*ptr, LogFile); 178 | ptr++; 179 | } 180 | else{ /* It's a Telnet command */ 181 | ptr++; 182 | Command = *ptr++; 183 | len--; 184 | if( Command == IAC ) /* double IAC means command terminated */ 185 | continue; 186 | Option = *ptr++; 187 | len--; 188 | 189 | switch(Option) { 190 | 191 | case TELOPT_ECHO: 192 | switch(Command){ 193 | case WILL: /* server WILL echo. Do it */ 194 | echo = 1; 195 | SendTC( DO, TELOPT_ECHO ); 196 | break; 197 | 198 | case WONT: 199 | echo = 0; 200 | SendTC( DONT, TELOPT_ECHO ); 201 | break; 202 | 203 | case DO: /* we won't echo no matter what */ 204 | case DONT: 205 | SendTC( WONT, TELOPT_ECHO ); 206 | break; 207 | } /* switch */ 208 | break; 209 | 210 | case TELOPT_SGA: /* suppress go ahead */ 211 | if( Command == WONT ) 212 | SendTC( DONT, TELOPT_SGA ); 213 | else if( Command == WILL){ 214 | SendTC( DO, TELOPT_SGA ); 215 | if(!echo) 216 | SendTC( DO, TELOPT_ECHO ); 217 | } 218 | break; 219 | 220 | case TELOPT_TTYPE: 221 | if( Command == DO ) /* we will send our terminal type */ 222 | SendTC( WILL, TELOPT_TTYPE ); 223 | else if( Command == SB ){ 224 | /* find end of subnegotiation */ 225 | for(; *ptr != SE; ptr++, len--); 226 | ptr++; len--; 227 | SendTC(SB, TELOPT_TTYPE); 228 | n = strlen(term); 229 | sb[0] = '\0'; 230 | memcpy(sb + 1, term, n); 231 | sb[n+1] = 0xFF; 232 | sb[n+2] = SE; 233 | SendPacket(sb, n + 3); 234 | } /* else if */ 235 | break; 236 | 237 | case TELOPT_NAWS: /* terminal window size */ 238 | if( Command == DO ){ 239 | SendTC( WILL, TELOPT_NAWS ); 240 | SendTC( SB, TELOPT_NAWS); 241 | sb[0] = 0; 242 | sb[1] = columns; 243 | sb[2] = 0; 244 | sb[3] = lines - statusline; 245 | sb[4] = IAC; 246 | sb[5] = SE; 247 | SendPacket(sb, 6); 248 | } 249 | break; 250 | 251 | default: 252 | switch(Command){ 253 | 254 | case WILL: 255 | case WONT: 256 | SendTC( DONT, Option ); 257 | break; 258 | 259 | case DO: 260 | case DONT: 261 | SendTC( WONT, Option ); 262 | break; 263 | } /* switch */ 264 | break; 265 | } /* switch */ 266 | } /* else */ 267 | }/* for */ 268 | 269 | return(0); 270 | 271 | } 272 | 273 | /* 274 | * Get command line arguments 275 | */ 276 | static void getargs(int argc, char *argv[]) 277 | { 278 | unsigned short i, n; 279 | char *s; 280 | #if defined (__386__) 281 | char usage[]="Usage: tel386 [options] remotehost\n" 282 | #else 283 | char usage[]="Usage: telnet [options] remotehost\n" 284 | #endif 285 | "Options:\n" 286 | "-t - terminal type (default: xterm)\n" 287 | "-p - remote port\n" 288 | "-k - path to keymap file\n" 289 | "-m - screen mode: 80x25 80x60 132x25 132x50\n" 290 | "-l - log session to file\n" 291 | "-b - Brailab PC adapter on COM[1234] port\n" 292 | "-P - use non privileged local port\n" 293 | "-S - disable status line\n" 294 | "-n - add CR if server sends only LF"; 295 | 296 | for(i = 1; i < argc; ++i){ 297 | s = argv[i]; 298 | if(*s != '-') break; 299 | switch (*++s){ 300 | case '\0': 301 | fatal(usage); 302 | 303 | case 't': 304 | if(*++s) 305 | term = s; 306 | else if(++i < argc) 307 | term = argv[i]; 308 | else 309 | fatal(usage); 310 | continue; 311 | 312 | case 'm': 313 | if(*++s){ 314 | for(n = 0; n < 4; n++) 315 | if(!strcmp(s, modes[n].mode)){ 316 | vidmode = modes[n].vidmode; 317 | break; 318 | } 319 | if(!vidmode) 320 | fatal(usage); 321 | } 322 | else if(++i < argc){ 323 | for(n = 0; n < 4; n++) 324 | if(!strcmp(argv[i], modes[n].mode)){ 325 | vidmode = modes[n].vidmode; 326 | break; 327 | } 328 | if(!vidmode) 329 | fatal(usage); 330 | } 331 | else 332 | fatal(usage); 333 | continue; 334 | 335 | case 'p': 336 | if(*++s) 337 | RemotePort = atoi(s); 338 | else if(++i < argc) 339 | RemotePort = atoi(argv[i]); 340 | else 341 | fatal(usage); 342 | continue; 343 | 344 | case 'b': 345 | if(*++s){ 346 | strupr(s); 347 | if(!strcmp(s, "COM1") || 348 | !strcmp(s, "COM2") || 349 | !strcmp(s, "COM3") || 350 | !strcmp(s, "COM4")){ 351 | if((GlobalConfig.brailab = fopen(s,"w+b")) == NULL){ 352 | fatal("Cannot open COM port"); 353 | } 354 | } 355 | else 356 | fatal(usage); 357 | } 358 | else if(++i < argc){ 359 | strupr(argv[i]); 360 | if(!strcmp(argv[i], "COM1") || 361 | !strcmp(argv[i], "COM2") || 362 | !strcmp(argv[i], "COM3") || 363 | !strcmp(argv[i], "COM4")){ 364 | if((GlobalConfig.brailab = fopen(argv[i],"w+b")) == NULL){ 365 | fatal("Cannot open COM port"); 366 | } 367 | } 368 | else 369 | fatal(usage); 370 | } 371 | else 372 | fatal(usage); 373 | continue; 374 | 375 | case 'k': 376 | if(*++s) 377 | keymap_init(s); 378 | else if(++i < argc) 379 | keymap_init(argv[i]); 380 | else 381 | fatal(usage); 382 | continue; 383 | 384 | case 'l': 385 | if(*++s){ 386 | if((LogFile = fopen(s,"w+b")) == NULL) 387 | fatal("Cannot create log file"); 388 | } 389 | else if(++i < argc){ 390 | if((LogFile = fopen(argv[i],"w+b")) == NULL) 391 | fatal("Cannot create log file"); 392 | } 393 | else 394 | fatal(usage); 395 | continue; 396 | 397 | case 'P': 398 | Configuration |= NONPRIVILEGED_PORT; 399 | continue; 400 | 401 | case 'S': 402 | statusline = 0; 403 | continue; 404 | 405 | case 'n': 406 | Configuration |= NEWLINE; 407 | continue; 408 | 409 | default: 410 | fatal(usage); 411 | } /* end switch */ 412 | 413 | } /* end for */ 414 | 415 | /* no_more_options */ 416 | if(i + 1 > argc) 417 | fatal(usage); 418 | RemoteHost = argv[i++]; 419 | } 420 | 421 | /* 422 | * Main program starts here 423 | */ 424 | int main(int argc, char **argv) 425 | { 426 | #if defined (__386__) 427 | printf("TELNET v%s. 386+ version\n", SSH_VERSION); 428 | #else 429 | printf("TELNET v%s\n", SSH_VERSION); 430 | #endif 431 | 432 | Config_Init(); /* Initialize global variables */ 433 | getargs(argc, argv); /* Process command line */ 434 | 435 | VESACheck(); 436 | SetMode(); 437 | VidParam(); /* Get proper screen size for PTY negotiation */ 438 | 439 | 440 | TCPConnect(RemoteHost, RemotePort); /* connect to server */ 441 | 442 | sock_mode(&GlobalConfig.s, TCP_MODE_NAGLE ); 443 | 444 | VidInit("user", RemoteHost); 445 | VTInit(); 446 | 447 | while(EXIT_TELNET != dosession()); /* Loop until session end */ 448 | 449 | VidUninit(); 450 | 451 | sock_close(&GlobalConfig.s); /* Close TCP socket */ 452 | 453 | /* Close open files */ 454 | if(GlobalConfig.brailab) 455 | fclose(GlobalConfig.brailab); 456 | if(LogFile) 457 | fclose(LogFile); 458 | 459 | return(0); 460 | } 461 | -------------------------------------------------------------------------------- /telnet.lnk: -------------------------------------------------------------------------------- 1 | System dos 2 | Name telnet.exe 3 | Debug all 4 | Option map 5 | File telnet.obj 6 | Library misc.lib,vt100.lib,wattcpwl.lib 7 | -------------------------------------------------------------------------------- /vidio.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnttiTakala/SSH2DOS/58fac356f5c597af5a2338286392598239f429b2/vidio.c -------------------------------------------------------------------------------- /vt100.kbd: -------------------------------------------------------------------------------- 1 | # vt100.kbd -- sshdos keymap for vt100 and vt102 terminals. 2 | # Written by Nagy Daniel 2002-02-11. 3 | # Based on the vt100 terminfo database entry. 4 | # Contains only differences to the original xterm keymap 5 | 6 | # key_backspace 7 | mapkey 0x0e08 \10 8 | # key_f1 9 | mapkey 0x3b00 \EOP 10 | # key_f2 11 | mapkey 0x3c00 \EOQ 12 | # key_f3 13 | mapkey 0x3d00 \EOR 14 | # key_f4 15 | mapkey 0x3e00 \EOS 16 | # key_f5 17 | mapkey 0x3f00 \EOt 18 | # key_f6 19 | mapkey 0x4000 \EOu 20 | # key_f7 21 | mapkey 0x4100 \EOv 22 | # key_f8 23 | mapkey 0x4200 \EOl 24 | # key_f9 25 | mapkey 0x4300 \EOw 26 | # key_f10 27 | mapkey 0x4400 \EOx 28 | -------------------------------------------------------------------------------- /vt340.kbd: -------------------------------------------------------------------------------- 1 | # vt340.kbd -- sshdos keymap for vt340 terminals. 2 | # Contains only differences to the original xterm keymap 3 | 4 | # key_backspace 5 | mapkey 0x0e08 \10 6 | # key_f1 7 | mapkey 0x3b00 \EOP 8 | # key_f2 9 | mapkey 0x3c00 \EOQ 10 | # key_f3 11 | mapkey 0x3d00 \EOR 12 | # key_f4 13 | mapkey 0x3e00 \EOS 14 | # key_f5 15 | mapkey 0x3f00 \E[15~\ 16 | # key_f6 17 | mapkey 0x4000 \E[17~\ 18 | # key_f7 19 | mapkey 0x4100 \EOW 20 | # key_f8 21 | mapkey 0x4200 \EOX 22 | # key_f9 23 | mapkey 0x4300 \EOY 24 | # key_f10 25 | mapkey 0x4400 \E[21~\ 26 | 27 | # key_insert 28 | mapkey 0x52e0 \E[2~\ 29 | # key_delete 30 | mapkey 0x53e0 \E[3~\ 31 | # key_home 32 | mapkey 0x47e0 \Eh\ 33 | # key_end 34 | mapkey 0x4fe0 \E[4~\ 35 | # key_page-up 36 | mapkey 0x49e0 \E[5~\ 37 | # key_page-down 38 | mapkey 0x51e0 \E[6~\ 39 | -------------------------------------------------------------------------------- /watcom_f.mak: -------------------------------------------------------------------------------- 1 | # 2 | # OpenWatcom makefile for SSH2DOS (protected mode version) 3 | # 4 | 5 | # Debug 6 | #DEBUG=-d2 7 | 8 | # uncomment this for B&W mode 9 | COLOR = -DCOLOR 10 | 11 | ################################################################# 12 | # In normal cases, no other settings should be changed below!!! # 13 | ################################################################# 14 | 15 | CC = wcc386 16 | LINKER = wlink LibPath lib;$(%WATT_ROOT)\lib 17 | 18 | CFLAGS = -zq -mf -3r -bt=dos -s $(DEBUG) -i=$(%WATCOM)\h;.\include;$(%WATT_ROOT)\inc $(COLOR) 19 | # -DMEMWATCH 20 | 21 | .C.OBJ: 22 | $(CC) $(CFLAGS) $[@ 23 | 24 | LIBS = lib\misc.lib lib\crypto.lib lib\ssh.lib lib\vt100.lib $(%WATT_ROOT)\lib\wattcpwf.lib lib\zlib_f.lib 25 | 26 | all: ssh2d386.exe sftpd386.exe scp2d386.exe tel386.exe 27 | 28 | ssh2d386.exe : ssh2dos.obj $(LIBS) 29 | $(LINKER) @ssh2d386.lnk 30 | 31 | sftpd386.exe : sftpdos.obj sftp.obj $(LIBS) 32 | $(LINKER) @sftpd386.lnk 33 | 34 | scp2d386.exe : scpdos.obj $(LIBS) 35 | $(LINKER) @scp2d386.lnk 36 | 37 | tel386.exe : telnet.obj lib\misc.lib lib\vt100.lib $(%WATT_ROOT)\lib\wattcpwf.lib 38 | $(LINKER) @tel386.lnk 39 | 40 | lib\crypto.lib: sshrsa.obj sshdes.obj sshmd5.obj sshbn.obj sshpubk.obj int64.obj sshaes.obj sshsha.obj sshsh512.obj sshdss.obj sshsh256.obj 41 | wlib -b -c lib\crypto.lib -+sshrsa.obj -+sshdes.obj -+sshmd5.obj -+sshbn.obj -+sshpubk.obj 42 | wlib -b -c lib\crypto.lib -+int64.obj -+sshaes.obj -+sshsha.obj -+sshsh512.obj -+sshdss.obj -+sshsh256.obj 43 | 44 | lib\ssh.lib: negotiat.obj transprt.obj auth.obj channel.obj 45 | wlib -b -c lib\ssh.lib -+negotiat.obj -+transprt.obj -+auth.obj -+channel.obj 46 | 47 | lib\vt100.lib: vttio.obj vidio.obj keyio.obj keymap.obj 48 | wlib -b -c lib\vt100.lib -+vttio.obj -+vidio.obj -+keyio.obj -+keymap.obj 49 | 50 | lib\misc.lib: common.obj shell.obj proxy.obj 51 | wlib -b -c lib\misc.lib -+common.obj -+shell.obj -+proxy.obj 52 | 53 | clean: .SYMBOLIC 54 | del *.obj 55 | del *.map 56 | del lib\vt100.lib 57 | del lib\crypto.lib 58 | del lib\misc.lib 59 | del lib\ssh.lib 60 | del ssh2d386.exe 61 | del sftpd386.exe 62 | del scp2d386.exe 63 | del tel386.exe 64 | -------------------------------------------------------------------------------- /watcom_l.mak: -------------------------------------------------------------------------------- 1 | # 2 | # OpenWatcom makefile for SSH2DOS (real mode - large) 3 | # 4 | 5 | # Debug 6 | #DEBUG=-d2 7 | 8 | # uncomment this for B&W mode 9 | COLOR = -DCOLOR 10 | 11 | ################################################################# 12 | # In normal cases, no other settings should be changed below!!! # 13 | ################################################################# 14 | 15 | CC = wcc 16 | LINKER = wlink LibPath lib;$(%WATT_ROOT)\lib 17 | 18 | CFLAGS = -zq -ml -0 -bt=dos -zt -s 19 | CFLAGS += $(DEBUG) -i=$(%WATCOM)\h;include;$(%WATT_ROOT)\inc $(COLOR) 20 | # -DMEMWATCH 21 | 22 | .C.OBJ: 23 | $(CC) $(CFLAGS) $[@ 24 | 25 | LIBS = lib\misc.lib lib\crypto.lib lib\ssh.lib lib\vt100.lib $(%WATT_ROOT)\lib\wattcpwl.lib lib\zlib_l.lib 26 | 27 | all: ssh2dos.exe sftpdos.exe scp2dos.exe telnet.exe 28 | 29 | ssh2dos.exe : ssh2dos.obj $(LIBS) 30 | $(LINKER) @ssh2dos.lnk 31 | 32 | sftpdos.exe : sftpdos.obj sftp.obj $(LIBS) 33 | $(LINKER) @sftpdos.lnk 34 | 35 | scp2dos.exe : scpdos.obj $(LIBS) 36 | $(LINKER) @scp2dos.lnk 37 | 38 | telnet.exe : telnet.obj lib\misc.lib lib\vt100.lib $(%WATT_ROOT)\lib\wattcpwl.lib 39 | $(LINKER) @telnet.lnk 40 | 41 | ttytest.exe : ttytest.obj $(LIBS) 42 | $(LINKER) @ttytest.lnk 43 | 44 | lib\crypto.lib: sshrsa.obj sshdes.obj sshmd5.obj sshbn.obj sshpubk.obj int64.obj sshaes.obj sshsha.obj sshsh512.obj sshdss.obj sshsh256.obj 45 | wlib -b -c lib\crypto.lib -+sshrsa.obj -+sshdes.obj -+sshmd5.obj -+sshbn.obj -+sshpubk.obj 46 | wlib -b -c lib\crypto.lib -+int64.obj -+sshaes.obj -+sshsha.obj -+sshsh512.obj -+sshdss.obj -+sshsh256.obj 47 | 48 | lib\ssh.lib: negotiat.obj transprt.obj auth.obj channel.obj 49 | wlib -b -c lib\ssh.lib -+negotiat.obj -+transprt.obj -+auth.obj -+channel.obj 50 | 51 | lib\vt100.lib: vttio.obj vidio.obj keyio.obj keymap.obj 52 | wlib -b -c lib\vt100.lib -+vttio.obj -+vidio.obj -+keyio.obj -+keymap.obj 53 | 54 | lib\misc.lib: common.obj shell.obj proxy.obj 55 | wlib -b -c lib\misc.lib -+common.obj -+shell.obj -+proxy.obj 56 | 57 | clean: .SYMBOLIC 58 | del *.obj 59 | del *.map 60 | del lib\vt100.lib 61 | del lib\crypto.lib 62 | del lib\misc.lib 63 | del lib\ssh.lib 64 | del ssh2dos.exe 65 | del scp2dos.exe 66 | del sftpdos.exe 67 | del telnet.exe 68 | del ttytest.exe 69 | -------------------------------------------------------------------------------- /x-color.kbd: -------------------------------------------------------------------------------- 1 | # x-color.kbd -- sshdos keymap for xterm-color terminals. 2 | # Written by Shane Wegner 2001-09-13. 3 | # Based on the xterm-color terminfo database entry. 4 | # Modified by Nagy Daniel 2002-02-11. 5 | # Contains only differences to the original xterm keymap 6 | 7 | # key_backspace 8 | mapkey 0x0e08 \10 9 | # key_delete 10 | mapkey 0x53e0 \177 11 | # key_home 12 | mapkey 0x47e0 \E[1~ 13 | # key_end 14 | mapkey 0x4fe0 \E[4~ 15 | # key_f1 16 | mapkey 0x3b00 \E[11~ 17 | # key_f2 18 | mapkey 0x3c00 \E[12~ 19 | # key_f3 20 | mapkey 0x3d00 \E[13~ 21 | # key_f4 22 | mapkey 0x3e00 \E[14~ 23 | --------------------------------------------------------------------------------