mpgp.c (6229B)
1 /* mpgp -- (C) 2000 - 2006 Ulf Moeller and others. 2 3 mpgp may be redistributed and modified under certain conditions. 4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 5 ANY KIND, either express or implied. See the file COPYRIGHT for 6 details. 7 8 Test application for OpenPGP features 9 $Id: mpgp.c 934 2006-06-24 13:40:39Z rabbi $ */ 10 11 #define MPGPVERSION "0.3.0" 12 13 #include "mix3.h" 14 #include "pgp.h" 15 #include <stdlib.h> 16 #include <string.h> 17 #include <fcntl.h> 18 #include <assert.h> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <time.h> 22 #include <fcntl.h> 23 #ifdef POSIX 24 #include <unistd.h> 25 #include <termios.h> 26 #endif /* POSIX */ 27 28 int pass(BUFFER *b) 29 { 30 char p[LINELEN]; 31 int fd; 32 int n; 33 34 #ifdef HAVE_TERMIOS 35 struct termios attr; 36 #endif /* HAVE_TERMIOS */ 37 38 fprintf(stderr, "enter passphrase: "); 39 fflush(stderr); 40 #ifdef HAVE_TERMIOS 41 fd = open("/dev/tty", O_RDONLY); 42 if (tcgetattr(fd, &attr) != 0) 43 return (-1); 44 attr.c_lflag &= ~ECHO; 45 attr.c_lflag |= ICANON; 46 if (tcsetattr(fd, TCSAFLUSH, &attr) != 0) 47 return (-1); 48 n = read(fd, p, LINELEN); 49 50 attr.c_lflag |= ECHO; 51 if (tcsetattr(fd, TCSAFLUSH, &attr) != 0) 52 return (-1); 53 close(fd); 54 p[n - 1] = 0; 55 56 #else /* end of HAVE_TERMIOS */ 57 fgets(p, LINELEN, stdin); 58 if (p[strlen(p)-1]=='\n') 59 p[strlen(p)-1] = 0; 60 #endif /* else if not HAVE_TERMIOS */ 61 62 fprintf(stderr, "\n"); 63 buf_appends(b, p); 64 return (0); 65 } 66 67 void usage(char *n) 68 { 69 fprintf(stderr, "Usage: %s -e [-b] user@domain\n", n); 70 fprintf(stderr, " %s -s [-b] [yourname@domain]\n", n); 71 fprintf(stderr, " %s -c [-b]\n", n); 72 fprintf(stderr, " %s -C [-b]\n", n); 73 fprintf(stderr, " %s -d [passphrase]\n", n); 74 fprintf(stderr, " %s -g[r] yourname@domain [bits]\n", n); 75 fprintf(stderr, " %s -a[+-] [-b]\n", n); 76 fprintf(stderr, " %s -V\n\n", n); 77 fprintf(stderr, "PGP public key ring: %s\n", PGPPUBRING); 78 fprintf(stderr, "PGP secret key ring: %s\n", PGPSECRING); 79 } 80 81 int decrypt(BUFFER *u, BUFFER *option, char *n) 82 { 83 BUFFER *v; 84 BUFFER *sig; 85 int err = 0; 86 87 v = buf_new(); 88 sig = buf_new(); 89 90 buf_set(v, u); 91 err = pgp_decrypt(v, NULL, sig, PGPPUBRING, PGPSECRING); 92 if (err >= 0 || err == PGP_SIGBAD) 93 buf_move(u, v); 94 95 if (err == PGP_ERR) { 96 pass(option); 97 err = pgp_decrypt(u, option, sig, PGPPUBRING, PGPSECRING); 98 } 99 switch (err) { 100 case PGP_NOMSG: 101 fprintf(stderr, "%s: Not a PGP message.\n", n); 102 break; 103 case PGP_ERR: 104 fprintf(stderr, "%s: Can't read message.\n", n); 105 break; 106 case PGP_SIGOK: 107 fprintf(stderr, "%s: Valid signature: %s\n", n, sig->data); 108 err = 0; 109 break; 110 case PGP_SIGNKEY: 111 fprintf(stderr, "%s: Unknown signature key %s, cannot verify.\n", n, sig->data); 112 err = 1; 113 break; 114 case PGP_SIGBAD: 115 fprintf(stderr, "%s: Bad signature.\n", n); 116 err = 1; 117 break; 118 } 119 120 buf_free(v); 121 buf_free(sig); 122 123 return (err); 124 } 125 126 int main(int argc, char *argv[]) 127 { 128 BUFFER *u, *option, *pp; 129 char *filename = NULL; 130 char *cmd = NULL; 131 int text = 1; 132 int err = 99; 133 int bits = 0; 134 135 mix_init(NULL); 136 VERBOSE = 3; 137 138 u = buf_new(); 139 option = buf_new(); 140 pp = buf_new(); 141 142 if (argc > 1 && argv[1][0] == '-') 143 cmd = argv[1]; 144 145 if (argc == 1 || (cmd > 0 && (cmd[1] == 'e' || cmd[1] == 'c' || 146 cmd[1] == 'd' || cmd[1] == 'a' || 147 cmd[1] == 's' || cmd[1] == 'C'))) { 148 if ((argc > 2 && (cmd == NULL || cmd[1] == 'a')) || argc > 3) { 149 FILE *f; 150 151 f = fopen(argv[argc - 1], "rb"); 152 if (f == NULL) { 153 fprintf(stderr, "%s: Can't open %s\n", argv[0], argv[argc - 1]); 154 err = -1; 155 } else { 156 buf_read(u, f); 157 fclose(f); 158 filename = argv[argc - 1]; 159 argc--; 160 } 161 } else 162 buf_read(u, stdin); 163 } 164 if (argc == 1) 165 err = decrypt(u, option, argv[0]); 166 167 if (argc > 2 && argv[2][0] == '-' && argv[2][1] == 'b') { 168 text = 0; 169 if (argc > 3) 170 buf_appends(option, argv[3]); 171 } else if (argc > 2) 172 buf_appends(option, argv[2]); 173 174 if (cmd) 175 switch (cmd[1]) { 176 case 's': 177 err = pgp_encrypt(PGP_SIGN | (text ? PGP_TEXT : 0), u, NULL, option, 178 NULL, PGPPUBRING, PGPSECRING); 179 if (err != 0) { 180 pass(pp); 181 err = pgp_encrypt(PGP_SIGN | (text ? PGP_TEXT : 0), u, NULL, option, 182 pp, PGPPUBRING, PGPSECRING); 183 } 184 if (err != 0) 185 fprintf(stderr, "Error.\n"); 186 break; 187 case 'e': 188 if (option->length) { 189 err = pgp_encrypt(PGP_ENCRYPT | (text ? PGP_TEXT : 0), u, option, NULL, 190 NULL, PGPPUBRING, PGPSECRING); 191 if (err < 0) 192 fprintf(stderr, "%s: can't encrypt message for %s\n", 193 argv[0], argv[2]); 194 } 195 break; 196 case 'c': 197 pass(option); 198 err = pgp_encrypt(PGP_CONVENTIONAL | (text ? PGP_TEXT : 0), u, option, 199 NULL, NULL, PGPPUBRING, PGPSECRING); 200 if (err < 0) 201 fprintf(stderr, "%s: can't encrypt message\n", argv[0]); 202 break; 203 case 'C': 204 pass(option); 205 err = pgp_encrypt(PGP_NCONVENTIONAL | (text ? PGP_TEXT : 0), u, option, 206 NULL, NULL, PGPPUBRING, PGPSECRING); 207 if (err < 0) 208 fprintf(stderr, "%s: can't encrypt message\n", argv[0]); 209 break; 210 case 'g': 211 if (argc < 3) { 212 err = 99; 213 goto end; 214 } 215 pass(pp); 216 if (argc == 4) 217 sscanf(argv[3], "%d", &bits); 218 err = pgp_keygen(cmd[2] == 'r' ? PGP_ES_RSA : PGP_E_ELG, 219 bits, option, pp, PGPPUBRING, PGPSECRING, 0); 220 break; 221 case 'a': 222 switch (cmd[2]) { 223 case '-': 224 err = pgp_dearmor(u, u); 225 if (err == -1) 226 fprintf(stderr, "Not a PGP-armored message\n"); 227 goto end; 228 case '+': 229 break; 230 default: 231 pgp_literal(u, filename, text); 232 pgp_compress(u); 233 break; 234 } 235 err = pgp_armor(u, PGP_ARMOR_NORMAL); 236 break; 237 case 'd': 238 err = decrypt(u, option, argv[0]); 239 break; 240 case 'h': 241 usage(argv[0]); 242 err = 0; 243 break; 244 case 'V': 245 fprintf(stderr, "mpgp version %s\n", MPGPVERSION); 246 fprintf(stderr, "(C) 2000 - 2004 Ulf Moeller and others.\n"); 247 fprintf(stderr, "See the file COPYRIGHT for details.\n"); 248 err = 0; 249 break; 250 } 251 end: 252 if (err == 99) 253 usage(argv[0]); 254 255 if (err >= 0) 256 buf_write(u, stdout); 257 258 buf_free(option); 259 buf_free(pp); 260 buf_free(u); 261 262 mix_exit(); 263 return (err == -1 ? 1 : err); 264 }