1/* 2 * Copyright (c) 1995, Cyclic Software, Bloomington, IN, USA 3 * 4 * You may distribute under the terms of the GNU General Public License as 5 * specified in the README file that comes with CVS. 6 * 7 * Allow user to log in for an authenticating server. 8 * |
9 * $FreeBSD: head/contrib/cvs/src/login.c 128269 2004-04-15 01:17:28Z peter $ |
10 */ 11 12#include "cvs.h" 13#include "getline.h" 14 15#ifdef AUTH_CLIENT_SUPPORT /* This covers the rest of the file. */ 16 |
17/* There seems to be very little agreement on which system header 18 getpass is declared in. With a lot of fancy autoconfiscation, 19 we could perhaps detect this, but for now we'll just rely on 20 _CRAY, since Cray is perhaps the only system on which our own 21 declaration won't work (some Crays declare the 2#$@% thing as 22 varadic, believe it or not). On Cray, getpass will be declared 23 in either stdlib.h or unistd.h. */ |
24 25#ifndef CVS_PASSWORD_FILE 26#define CVS_PASSWORD_FILE ".cvspass" 27#endif 28 29/* If non-NULL, get_cvs_password() will just return this. */ 30static char *cvs_password = NULL; 31 --- 185 unchanged lines hidden (view full) --- 217 * cvsroot_t *root, 218 * char *newpassword 219 * ); 220 * 221 * Search the password file and depending on the value of operation: 222 * 223 * Mode Action 224 * password_entry_lookup Return the password |
225 * password_entry_delete Delete the entry from the file, if it 226 * exists. 227 * password_entry_add Replace the line with the new one, else 228 * append it. |
229 * 230 * Because the user might be accessing multiple repositories, with 231 * different passwords for each one, the format of ~/.cvspass is: 232 * 233 * [user@]host:[port]/path Aencoded_password 234 * [user@]host:[port]/path Aencoded_password 235 * ... 236 * --- 44 unchanged lines hidden (view full) --- 281 cvsroot_t *root; 282 char *newpassword; 283{ 284 char *passfile; 285 FILE *fp; 286 char *cvsroot_canonical = NULL; 287 char *password = NULL; 288 int line_length; |
289 long line = -1; |
290 char *linebuf = NULL; 291 size_t linebuf_len; 292 char *p; 293 int save_errno = 0; 294 295 if (root->method != pserver_method) 296 { |
297 error (0, 0, "\ 298internal error: can only call password_entry_operation with pserver method"); |
299 error (1, 0, "CVSROOT: %s", root->original); 300 } 301 302 cvsroot_canonical = normalize_cvsroot (root); 303 304 /* Yes, the method below reads the user's password file twice when we have 305 * to delete an entry. It's inefficient, but we're not talking about a gig of 306 * data here. --- 7 unchanged lines hidden (view full) --- 314 goto process; 315 } 316 317 /* Check each line to see if we have this entry already. */ 318 line = 0; 319 while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0) 320 { 321 line++; |
322 password = password_entry_parseline (cvsroot_canonical, 1, line, 323 linebuf); |
324 if (password != NULL) 325 /* this is it! break out and deal with linebuf */ 326 break; 327 } 328 if (line_length < 0 && !feof (fp)) 329 { 330 error (0, errno, "cannot read %s", passfile); 331 goto error_exit; --- 33 unchanged lines hidden (view full) --- 365 * anything else if we're in lookup mode 366 */ 367 368 /* copy the file with the entry deleted unless we're in add 369 * mode and the line we found contains the same password we're supposed to 370 * add 371 */ 372 if (!noexec && password != NULL && (operation == password_entry_delete |
373 || (operation == password_entry_add 374 && strcmp (password, newpassword)))) |
375 { 376 long found_at = line; 377 char *tmp_name; 378 FILE *tmp_fp; 379 380 /* open the original file again */ 381 fp = CVS_FOPEN (passfile, "r"); 382 if (fp == NULL) --- 4 unchanged lines hidden (view full) --- 387 error (1, errno, "unable to open temp file %s", tmp_name); 388 389 line = 0; 390 while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0) 391 { 392 line++; 393 if (line < found_at 394 || (line != found_at |
395 && !password_entry_parseline (cvsroot_canonical, 0, line, 396 linebuf))) |
397 { 398 if (fprintf (tmp_fp, "%s", linebuf) == EOF) 399 { 400 /* try and clean up anyhow */ 401 error (0, errno, "fatal error: cannot write %s", tmp_name); 402 if (fclose (tmp_fp) == EOF) 403 error (0, errno, "cannot close %s", tmp_name); 404 /* call CVS_UNLINK instead of unlink_file since the file --- 130 unchanged lines hidden (view full) --- 535 536 if (current_parsed_root->password) 537 { 538 typed_password = scramble (current_parsed_root->password); 539 } 540 else 541 { 542 char *tmp; |
543 tmp = getpass ("CVS password: "); |
544 /* Must deal with a NULL return value here. I haven't managed to 545 * disconnect the CVS process from the tty and force a NULL return 546 * in sanity.sh, but the Linux version of getpass is documented 547 * to return NULL when it can't open /dev/tty... 548 */ 549 if (!tmp) error (1, errno, "login: Failed to read password."); 550 typed_password = scramble (tmp); 551 memset (tmp, 0, strlen (tmp)); 552 } 553 554 /* Force get_cvs_password() to use this one (when the client 555 * confirms the new password with the server), instead of 556 * consulting the file. We make a new copy because cvs_password 557 * will get zeroed by connect_to_server(). */ 558 cvs_password = xstrdup (typed_password); 559 560 connect_to_pserver (current_parsed_root, NULL, NULL, 1, 0); 561 |
562 password_entry_operation (password_entry_add, current_parsed_root, 563 typed_password); |
564 565 memset (typed_password, 0, strlen (typed_password)); 566 free (typed_password); 567 568 free (cvs_password); 569 free (cvsroot_canonical); 570 cvs_password = NULL; 571 572 return 0; 573} 574 |
575 576 |
577/* Returns the _scrambled_ password. The server must descramble 578 before hashing and comparing. If password file not found, or 579 password not found in the file, just return NULL. */ 580char * 581get_cvs_password () 582{ 583 if (current_parsed_root->password) |
584 return scramble (current_parsed_root->password); |
585 586 /* If someone (i.e., login()) is calling connect_to_pserver() out of 587 context, then assume they have supplied the correct, scrambled 588 password. */ 589 if (cvs_password) 590 return cvs_password; 591 592 if (getenv ("CVS_PASSWORD") != NULL) --- 11 unchanged lines hidden (view full) --- 604 } 605 606 if (current_parsed_root->method != pserver_method) 607 { 608 error (0, 0, "can only call get_cvs_password with pserver method"); 609 error (1, 0, "CVSROOT: %s", current_parsed_root->original); 610 } 611 |
612 return password_entry_operation (password_entry_lookup, 613 current_parsed_root, NULL); |
614} 615 |
616 617 |
618static const char *const logout_usage[] = 619{ 620 "Usage: %s %s\n", 621 "(Specify the --help global option for a list of other help options)\n", 622 NULL 623}; 624 625/* Remove any entry for the CVSRoot repository found in .cvspass. */ --- 38 unchanged lines hidden --- |