menunym.c (11544B)
1 /* Mixmaster version 3.0 -- (C) 1999 - 2006 Anonymizer Inc. and others. 2 3 Mixmaster 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 Menu-based user interface - nym management 9 $Id: menunym.c 934 2006-06-24 13:40:39Z rabbi $ */ 10 11 #ifdef NYMSUPPORT 12 13 #include "menu.h" 14 #include "mix3.h" 15 #include <string.h> 16 #include <stdlib.h> 17 #ifdef POSIX 18 #include <unistd.h> 19 #endif /* POSIX */ 20 21 #ifdef USE_NCURSES 22 void menu_nym(char *nnym) 23 { 24 char nym[maxnym][LINELEN]; 25 char pending[maxnym][LINELEN]; 26 int c, i, num = 0, numpending = 0, select = -1; 27 int edit = 0; 28 BUFFER *nymlist; 29 int s; 30 int pass = 0; 31 char reliability[9]; /* When printing information about a chain, 32 this variable stores the reliability. */ 33 34 nymlist = buf_new(); 35 36 strcpy(nym[0], NONANON); 37 strcatn(nym[0], " (", sizeof(nym[0])); 38 strcatn(nym[0], NAME, sizeof(nym[0])); 39 strcatn(nym[0], ")", sizeof(nym[0])); 40 41 strcpy(nym[1], ANON); 42 num = 2; 43 if (nymlist_read(nymlist) == -1) { 44 user_delpass(); 45 mix_status(""); 46 } else 47 pass = 1; 48 while (nymlist_get(nymlist, nym[num], NULL, NULL, NULL, NULL, NULL, &s) >= 0) { 49 if (s == NYM_OK) { 50 if (num < maxnym) 51 num++; 52 } else if (s == NYM_WAITING) { 53 if (numpending < maxnym) 54 strncpy(pending[numpending++], nym[num], LINELEN); 55 } 56 } 57 buf_free(nymlist); 58 59 nymselect: 60 clear(); 61 standout(); 62 printw("Select nym:\n\n"); 63 standend(); 64 #ifdef USE_PGP 65 if (pass) 66 printw("c)reate new nym\ne)dit nym\nd)elete nym\n\n"); 67 else 68 printw("[nym passphrase is invalid]\n\n"); 69 #endif /* USE_PGP */ 70 for (i = 0; i < num; i++) 71 printw("%d) %s\n", i, nym[i]); 72 if (numpending > 0) { 73 printw("\n\nWaiting for confirmation: "); 74 for (i = 0; i < numpending; i++) 75 printw("%s ", pending[i]); 76 printw("\n"); 77 } 78 select: 79 if (select != -1) 80 printw("\r%d", select); 81 else 82 printw("\r \r"); 83 refresh(); 84 c = getch(); 85 if (c == erasechar()) 86 c = KEY_BACKSPACE; 87 if (c >= '0' && c <= '9') { 88 if (select == -1) 89 select = c - '0'; 90 else 91 select = 10 * select + c - '0'; 92 if (edit ? select == 0 || select >= num + numpending - 1 : select >= num) { 93 beep(); 94 select = -1; 95 } 96 refresh(); 97 goto select; 98 } else 99 switch (c) { 100 case KEY_BACKSPACE: 101 select /= 10; 102 if (select < 1) 103 select = -1; 104 goto select; 105 case 'q': 106 if (edit) { 107 edit = 0; 108 select = -1; 109 goto nymselect; 110 } 111 break; 112 #ifdef USE_PGP 113 case 'e': 114 if (pass) { 115 if (edit || num + numpending < 3) { 116 edit = 0; 117 select = -1; 118 goto nymselect; 119 } else { 120 clear(); 121 standout(); 122 printw("Edit nym:\n\n"); 123 standend(); 124 for (i = 2; i < num + numpending; i++) 125 printw("%d) %s\n", i - 1, i < num ? nym[i] : pending[i - num]); 126 printw("\n"); 127 select = -1; 128 edit = NYM_MODIFY; 129 goto select; 130 } 131 } 132 break; 133 case 'd': 134 if (pass) { 135 if (edit || num + numpending < 3) { 136 edit = 0; 137 select = -1; 138 goto nymselect; 139 } else { 140 clear(); 141 standout(); 142 printw("Delete nym:\n\n"); 143 standend(); 144 for (i = 2; i < num + numpending; i++) 145 printw("%d) %s\n", i - 1, i < num ? nym[i] : pending[i - num]); 146 printw("\n"); 147 select = -1; 148 edit = NYM_DELETE; 149 goto select; 150 } 151 } 152 break; 153 case '\r': 154 case '\n': 155 if (select == -1 || (edit && select == 0)) { 156 beep(); 157 edit = 0; 158 select = -1; 159 goto nymselect; 160 } 161 if (!edit) { 162 strncpy(nnym, nym[select], LINELEN); 163 return; 164 } 165 /* fallthru */ 166 case 'c': 167 if (pass) { 168 char nymserv[LINELEN] = "*"; 169 char replyblock[5][CHAINMAX], dest[10][LINELEN]; 170 int latent[5], desttype[5]; 171 char mdest[LINELEN], pdest[LINELEN] = "alt.anonymous.messages", 172 psub[LINELEN] = ""; 173 int deflatent = 0, defdesttype = MSG_MAIL; 174 char alias[LINELEN] = ""; 175 BUFFER *name, *opt; 176 char sendchain[CHAINMAX]; 177 int sendnumcopies = 1, rnum = 1; 178 int i; 179 char line[LINELEN]; 180 int acksend = 0, signsend = 0, fixedsize = 0, disable = 0, 181 fingerkey = 1; 182 183 name = buf_new(); 184 opt = buf_new(); 185 strncpy(sendchain, CHAIN, CHAINMAX); 186 strncpy(mdest, ADDRESS, LINELEN); 187 if (edit) 188 strncpy(alias, select + 1 < num ? nym[select + 1] : 189 pending[select + 1 - num], LINELEN); 190 if (edit == NYM_MODIFY) { 191 nymlist_getnym(alias, NULL, NULL, opt, name, NULL); 192 acksend = bufifind(opt, "+acksend"); 193 signsend = bufifind(opt, "+signsend"); 194 fixedsize = bufifind(opt, "+fixedsize"); 195 disable = bufifind(opt, "+disable"); 196 fingerkey = bufifind(opt, "+fingerkey"); 197 rnum = -1; 198 } 199 newnym: 200 if (!edit) { 201 clear(); 202 standout(); 203 printw("Create a nym:"); 204 standend(); 205 206 mvprintw(3, 0, "Alias address: "); 207 echo(); 208 wgetnstr(stdscr, alias, LINELEN); 209 noecho(); 210 if (alias[0] == '\0') 211 goto end; 212 for (i = 0; alias[i] > ' ' && alias[i] != '@'; i++) ; 213 alias[i] = '\0'; 214 if (i == 0) 215 goto newnym; 216 mvprintw(4, 0, "Pseudonym: "); 217 echo(); 218 wgetnstr(stdscr, line, LINELEN); 219 noecho(); 220 buf_sets(name, line); 221 menu_chain(nymserv, 2, 0); 222 } 223 if (edit != NYM_DELETE) { 224 for (i = 0; i < 5; i++) { 225 desttype[i] = defdesttype; 226 latent[i] = deflatent; 227 dest[i][0] = '\0'; 228 strcpy(replyblock[i], "*,*,*,*"); 229 } 230 if (rnum != -1) { 231 menu_replychain(&defdesttype, &deflatent, mdest, pdest, psub, 232 replyblock[0]); 233 desttype[0] = defdesttype; 234 latent[0] = deflatent; 235 strncpy(dest[0], desttype[0] == MSG_POST ? pdest : mdest, 236 LINELEN); 237 } 238 } 239 redraw: 240 clear(); 241 standout(); 242 switch (edit) { 243 case NYM_DELETE: 244 printw("Delete nym:"); 245 break; 246 case NYM_MODIFY: 247 printw("Edit nym:"); 248 break; 249 default: 250 printw("Create a nym:"); 251 break; 252 } 253 standend(); 254 loop: 255 { 256 if (!edit) { 257 cl(2, 0); 258 printw("Nym: a)lias address: %s", alias); 259 cl(3, 0); 260 printw(" nym s)erver: %s", nymserv); 261 } 262 if (edit != NYM_DELETE) { 263 cl(4, 0); 264 printw(" p)seudonym: %s", name->data); 265 if (edit) 266 mvprintw(6, 0, "Nym modification:"); 267 else 268 mvprintw(6, 0, "Nym creation:"); 269 } 270 cl(7, 0); 271 chain_reliability(sendchain, 0, reliability); /* chaintype 0=mix */ 272 printw(" c)hain to nym server: %-30s (reliability: %s)", sendchain, reliability); 273 cl(8, 0); 274 printw(" n)umber of redundant copies: %d", sendnumcopies); 275 if (edit != NYM_DELETE) { 276 mvprintw(10, 0, "Configuration:\n"); 277 printw(" A)cknowledge sending: %s\n", acksend ? "yes" : "no"); 278 printw(" S)erver signatures: %s\n", signsend ? "yes" : "no"); 279 printw(" F)ixed size replies: %s\n", fixedsize ? "yes" : 280 "no"); 281 printw(" D)isable: %s\n", disable ? "yes" : "no"); 282 printw(" Finger K)ey: %s\n", fingerkey ? "yes" : "no"); 283 mvprintw(17, 0, "Reply chains:"); 284 cl(18, 0); 285 if (rnum == -1) 286 printw(" create new r)eply block"); 287 else { 288 printw(" number of r)eply chains: %2d reliability", rnum); 289 for (i = 0; i < rnum; i++) { 290 cl(i + 19, 0); 291 chain_reliability(replyblock[i], 1, reliability); /* 1=ek */ 292 printw(" %d) %30s %-31s [%s]", i + 1, 293 desttype[i] == MSG_NULL ? 294 "(cover traffic)" : dest[i], replyblock[i], 295 reliability); 296 } 297 } 298 } 299 move(LINES - 1, COLS - 1); 300 refresh(); 301 c = getch(); 302 if (edit != NYM_DELETE && c >= '1' && c <= '9' && c - '1' < rnum) { 303 menu_replychain(&defdesttype, &deflatent, mdest, pdest, psub, 304 replyblock[c - '1']); 305 desttype[c - '1'] = defdesttype; 306 latent[c - '1'] = deflatent; 307 strncpy(dest[c - '1'], 308 desttype[c - '1'] == MSG_POST ? pdest : mdest, LINELEN); 309 goto redraw; 310 } 311 switch (c) { 312 case 'A': 313 acksend = !acksend; 314 goto redraw; 315 case 'S': 316 signsend = !signsend; 317 goto redraw; 318 case 'F': 319 fixedsize = !fixedsize; 320 goto redraw; 321 case 'D': 322 disable = !disable; 323 goto redraw; 324 case 'K': 325 fingerkey = !fingerkey; 326 goto redraw; 327 case 'q': 328 edit = 0; 329 select = -1; 330 goto nymselect; 331 case '\014': 332 goto redraw; 333 case 'a': 334 cl(2, 0); 335 printw("Nym: a)lias address: "); 336 echo(); 337 wgetnstr(stdscr, alias, LINELEN); 338 noecho(); 339 for (i = 0; alias[i] > ' ' && alias[i] != '@'; i++) ; 340 alias[i] = '\0'; 341 if (i == 0) 342 goto nymselect; 343 goto redraw; 344 case 'p': 345 cl(4, 0); 346 printw(" p)seudonym: "); 347 echo(); 348 wgetnstr(stdscr, line, LINELEN); 349 noecho(); 350 if (line[0] != '\0') 351 buf_sets(name, line); 352 goto redraw; 353 case 'c': 354 menu_chain(sendchain, 0, 0); 355 goto redraw; 356 case 'n': 357 cl(8, 0); 358 printw(" n)umber of redundant copies: "); 359 echo(); 360 wgetnstr(stdscr, line, LINELEN); 361 noecho(); 362 sendnumcopies = strtol(line, NULL, 10); 363 if (sendnumcopies < 1 || sendnumcopies > 10) 364 sendnumcopies = 1; 365 goto redraw; 366 case 'r': 367 cl(18, 0); 368 printw(" number of r)eply chains: "); 369 echo(); 370 wgetnstr(stdscr, line, LINELEN); 371 noecho(); 372 i = rnum; 373 rnum = strtol(line, NULL, 10); 374 if (rnum < 1) 375 rnum = 1; 376 if (rnum > 5) 377 rnum = 5; 378 for (; i < rnum; i++) 379 if (dest[i][0] == '\0') { 380 desttype[i] = defdesttype; 381 latent[i] = deflatent; 382 strncpy(dest[i], defdesttype == MSG_POST ? pdest : 383 mdest, LINELEN); 384 } 385 goto redraw; 386 case 's': 387 menu_chain(nymserv, 2, 0); 388 goto redraw; 389 case '\n': 390 case '\r': 391 { 392 BUFFER *chains; 393 int err; 394 395 if (rnum == -1) 396 chains = NULL; 397 else { 398 chains = buf_new(); 399 for (i = 0; i < rnum; i++) 400 if (replyblock[i][0] != '\0') { 401 if (desttype[i] == MSG_POST) 402 buf_appendf(chains, "Subject: %s\n", psub); 403 if (desttype[i] == MSG_MAIL) 404 buf_appends(chains, "To: "); 405 else if (desttype[i] == MSG_POST) 406 buf_appends(chains, "Newsgroups: "); 407 else 408 buf_appends(chains, "Null:"); 409 buf_appendf(chains, "%s\n", dest[i]); 410 buf_appendf(chains, "Chain: %s\n", replyblock[i]); 411 buf_appendf(chains, "Latency: %d\n\n", latent[i]); 412 } 413 } 414 create: 415 clear(); 416 buf_setf(opt, 417 " %cacksend %csignsend +cryptrecv %cfixedsize %cdisable %cfingerkey", 418 acksend ? '+' : '-', 419 signsend ? '+' : '-', 420 fixedsize ? '+' : '-', 421 disable ? '+' : '-', 422 fingerkey ? '+' : '-'); 423 if (edit) { 424 mix_status("Preparing nymserver configuration message..."); 425 err = nym_config(edit, alias, NULL, 426 name, sendchain, sendnumcopies, 427 chains, opt); 428 } else { 429 mix_status("Preparing nym creation request..."); 430 err = nym_config(edit, alias, nymserv, name, 431 sendchain, sendnumcopies, chains, 432 opt); 433 } 434 if (err == -3) { 435 beep(); 436 mix_status("Bad passphrase!"); 437 getch(); 438 goto create; 439 } 440 if (err != 0) { 441 mix_genericerror(); 442 beep(); 443 refresh(); 444 } else { 445 if (edit) 446 mix_status("Nymserver configuration message completed."); 447 else 448 mix_status("Nym creation request completed."); 449 } 450 if (chains) 451 buf_free(chains); 452 goto end; 453 } 454 default: 455 beep(); 456 goto loop; 457 } 458 } 459 end: 460 buf_free(name); 461 buf_free(opt); 462 return; 463 } 464 #endif /* USE_PGP */ 465 default: 466 beep(); 467 goto select; 468 } 469 } 470 471 #endif /* USE_NCURSES */ 472 #endif /* NYMSUPPORT */