1 /* This program is free software; you can redistribute it and/or modify 2 it under the terms of the GNU General Public License as published by 3 the Free Software Foundation; either version 2, or (at your option) 4 any later version. 5 6 This program is distributed in the hope that it will be useful, 7 but WITHOUT ANY WARRANTY; without even the implied warranty of 8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 GNU General Public License for more details. */ 10 11 #include <assert.h> 12 #include "cvs.h" 13 #include "watch.h" 14 #include "edit.h" 15 #include "fileattr.h" 16 #include "getline.h" 17 #include "buffer.h" 18 19 #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) 20 # ifdef HAVE_GSSAPI 21 /* This stuff isn't included solely with SERVER_SUPPORT since some of these 22 * functions (encryption & the like) get compiled with or without server 23 * support. 24 * 25 * FIXME - They should be in a different file. 26 */ 27 # include <netdb.h> 28 # include "xgssapi.h" 29 /* We use Kerberos 5 routines to map the GSSAPI credential to a user 30 name. */ 31 # include <krb5.h> 32 33 /* We need this to wrap data. */ 34 static gss_ctx_id_t gcontext; 35 36 static void gserver_authenticate_connection PROTO((void)); 37 38 /* Whether we are already wrapping GSSAPI communication. */ 39 static int cvs_gssapi_wrapping; 40 41 # ifdef ENCRYPTION 42 /* Whether to encrypt GSSAPI communication. We use a global variable 43 like this because we use the same buffer type (gssapi_wrap) to 44 handle both authentication and encryption, and we don't want 45 multiple instances of that buffer in the communication stream. */ 46 int cvs_gssapi_encrypt; 47 # endif 48 # endif /* HAVE_GSSAPI */ 49 #endif /* defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) */ 50 51 #ifdef SERVER_SUPPORT 52 53 #ifdef HAVE_WINSOCK_H 54 #include <winsock.h> 55 #endif 56 57 #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI) 58 #include <sys/socket.h> 59 #endif 60 61 #ifdef HAVE_SYSLOG_H 62 #include <syslog.h> 63 #endif 64 65 #ifdef HAVE_KERBEROS 66 # include <netinet/in.h> 67 # include <krb.h> 68 # ifndef HAVE_KRB_GET_ERR_TEXT 69 # define krb_get_err_text(status) krb_err_txt[status] 70 # endif 71 72 /* Information we need if we are going to use Kerberos encryption. */ 73 static C_Block kblock; 74 static Key_schedule sched; 75 76 #endif 77 78 /* for select */ 79 #include "xselect.h" 80 81 #ifndef O_NONBLOCK 82 #define O_NONBLOCK O_NDELAY 83 #endif 84 85 /* EWOULDBLOCK is not defined by POSIX, but some BSD systems will 86 return it, rather than EAGAIN, for nonblocking writes. */ 87 #ifdef EWOULDBLOCK 88 #define blocking_error(err) ((err) == EWOULDBLOCK || (err) == EAGAIN) 89 #else 90 #define blocking_error(err) ((err) == EAGAIN) 91 #endif 92 93 /* For initgroups(). */ 94 #if HAVE_INITGROUPS 95 #include <grp.h> 96 #endif /* HAVE_INITGROUPS */ 97 98 # ifdef AUTH_SERVER_SUPPORT 99 100 # ifdef HAVE_GETSPNAM 101 # include <shadow.h> 102 # endif 103 104 /* The cvs username sent by the client, which might or might not be 105 the same as the system username the server eventually switches to 106 run as. CVS_Username gets set iff password authentication is 107 successful. */ 108 char *CVS_Username = NULL; 109 110 /* Used to check that same repos is transmitted in pserver auth and in 111 later CVS protocol. Exported because root.c also uses. */ 112 static char *Pserver_Repos = NULL; 113 114 /* Should we check for system usernames/passwords? Can be changed by 115 CVSROOT/config. */ 116 int system_auth = 1; 117 118 # endif /* AUTH_SERVER_SUPPORT */ 119 120 121 /* While processing requests, this buffer accumulates data to be sent to 122 the client, and then once we are in do_cvs_command, we use it 123 for all the data to be sent. */ 124 static struct buffer *buf_to_net; 125 126 /* This buffer is used to read input from the client. */ 127 static struct buffer *buf_from_net; 128 129 /* 130 * This is where we stash stuff we are going to use. Format string 131 * which expects a single directory within it, starting with a slash. 132 */ 133 static char *server_temp_dir; 134 135 /* This is the original value of server_temp_dir, before any possible 136 changes inserted by serve_max_dotdot. */ 137 static char *orig_server_temp_dir; 138 139 /* Nonzero if we should keep the temp directory around after we exit. */ 140 static int dont_delete_temp; 141 142 static void server_write_entries PROTO((void)); 143 144 /* All server communication goes through buffer structures. Most of 145 the buffers are built on top of a file descriptor. This structure 146 is used as the closure field in a buffer. */ 147 148 struct fd_buffer 149 { 150 /* The file descriptor. */ 151 int fd; 152 /* Nonzero if the file descriptor is in blocking mode. */ 153 int blocking; 154 }; 155 156 static struct buffer *fd_buffer_initialize 157 PROTO ((int, int, void (*) (struct buffer *))); 158 static int fd_buffer_input PROTO((void *, char *, int, int, int *)); 159 static int fd_buffer_output PROTO((void *, const char *, int, int *)); 160 static int fd_buffer_flush PROTO((void *)); 161 static int fd_buffer_block PROTO((void *, int)); 162 static int fd_buffer_shutdown PROTO((void *)); 163 164 /* Initialize a buffer built on a file descriptor. FD is the file 165 descriptor. INPUT is nonzero if this is for input, zero if this is 166 for output. MEMORY is the function to call when a memory error 167 occurs. */ 168 169 static struct buffer * 170 fd_buffer_initialize (fd, input, memory) 171 int fd; 172 int input; 173 void (*memory) PROTO((struct buffer *)); 174 { 175 struct fd_buffer *n; 176 177 n = (struct fd_buffer *) xmalloc (sizeof *n); 178 n->fd = fd; 179 n->blocking = 1; 180 return buf_initialize (input ? fd_buffer_input : NULL, 181 input ? NULL : fd_buffer_output, 182 input ? NULL : fd_buffer_flush, 183 fd_buffer_block, 184 fd_buffer_shutdown, 185 memory, 186 n); 187 } 188 189 /* The buffer input function for a buffer built on a file descriptor. */ 190 191 static int 192 fd_buffer_input (closure, data, need, size, got) 193 void *closure; 194 char *data; 195 int need; 196 int size; 197 int *got; 198 { 199 struct fd_buffer *fd = (struct fd_buffer *) closure; 200 int nbytes; 201 202 if (! fd->blocking) 203 nbytes = read (fd->fd, data, size); 204 else 205 { 206 /* This case is not efficient. Fortunately, I don't think it 207 ever actually happens. */ 208 nbytes = read (fd->fd, data, need == 0 ? 1 : need); 209 } 210 211 if (nbytes > 0) 212 { 213 *got = nbytes; 214 return 0; 215 } 216 217 *got = 0; 218 219 if (nbytes == 0) 220 { 221 /* End of file. This assumes that we are using POSIX or BSD 222 style nonblocking I/O. On System V we will get a zero 223 return if there is no data, even when not at EOF. */ 224 return -1; 225 } 226 227 /* Some error occurred. */ 228 229 if (blocking_error (errno)) 230 { 231 /* Everything's fine, we just didn't get any data. */ 232 return 0; 233 } 234 235 return errno; 236 } 237 238 /* The buffer output function for a buffer built on a file descriptor. */ 239 240 static int 241 fd_buffer_output (closure, data, have, wrote) 242 void *closure; 243 const char *data; 244 int have; 245 int *wrote; 246 { 247 struct fd_buffer *fd = (struct fd_buffer *) closure; 248 249 *wrote = 0; 250 251 while (have > 0) 252 { 253 int nbytes; 254 255 nbytes = write (fd->fd, data, have); 256 257 if (nbytes <= 0) 258 { 259 if (! fd->blocking 260 && (nbytes == 0 || blocking_error (errno))) 261 { 262 /* A nonblocking write failed to write any data. Just 263 return. */ 264 return 0; 265 } 266 267 /* Some sort of error occurred. */ 268 269 if (nbytes == 0) 270 return EIO; 271 272 return errno; 273 } 274 275 *wrote += nbytes; 276 data += nbytes; 277 have -= nbytes; 278 } 279 280 return 0; 281 } 282 283 /* The buffer flush function for a buffer built on a file descriptor. */ 284 285 /*ARGSUSED*/ 286 static int 287 fd_buffer_flush (closure) 288 void *closure; 289 { 290 /* Nothing to do. File descriptors are always flushed. */ 291 return 0; 292 } 293 294 /* The buffer block function for a buffer built on a file descriptor. */ 295 296 static int 297 fd_buffer_block (closure, block) 298 void *closure; 299 int block; 300 { 301 struct fd_buffer *fd = (struct fd_buffer *) closure; 302 int flags; 303 304 flags = fcntl (fd->fd, F_GETFL, 0); 305 if (flags < 0) 306 return errno; 307 308 if (block) 309 flags &= ~O_NONBLOCK; 310 else 311 flags |= O_NONBLOCK; 312 313 if (fcntl (fd->fd, F_SETFL, flags) < 0) 314 return errno; 315 316 fd->blocking = block; 317 318 return 0; 319 } 320 321 /* The buffer shutdown function for a buffer built on a file descriptor. */ 322 323 static int 324 fd_buffer_shutdown (closure) 325 void *closure; 326 { 327 free (closure); 328 return 0; 329 } 330 331 /* Populate all of the directories between BASE_DIR and its relative 332 subdirectory DIR with CVSADM directories. Return 0 for success or 333 errno value. */ 334 static int create_adm_p PROTO((char *, char *)); 335 336 static int 337 create_adm_p (base_dir, dir) 338 char *base_dir; 339 char *dir; 340 { 341 char *dir_where_cvsadm_lives, *dir_to_register, *p, *tmp; 342 int retval, done; 343 FILE *f; 344 345 if (strcmp (dir, ".") == 0) 346 return 0; /* nothing to do */ 347 348 /* Allocate some space for our directory-munging string. */ 349 p = malloc (strlen (dir) + 1); 350 if (p == NULL) 351 return ENOMEM; 352 353 dir_where_cvsadm_lives = malloc (strlen (base_dir) + strlen (dir) + 100); 354 if (dir_where_cvsadm_lives == NULL) 355 return ENOMEM; 356 357 /* Allocate some space for the temporary string in which we will 358 construct filenames. */ 359 tmp = malloc (strlen (base_dir) + strlen (dir) + 100); 360 if (tmp == NULL) 361 return ENOMEM; 362 363 364 /* We make several passes through this loop. On the first pass, 365 we simply create the CVSADM directory in the deepest directory. 366 For each subsequent pass, we try to remove the last path 367 element from DIR, create the CVSADM directory in the remaining 368 pathname, and register the subdirectory in the newly created 369 CVSADM directory. */ 370 371 retval = done = 0; 372 373 strcpy (p, dir); 374 strcpy (dir_where_cvsadm_lives, base_dir); 375 strcat (dir_where_cvsadm_lives, "/"); 376 strcat (dir_where_cvsadm_lives, p); 377 dir_to_register = NULL; 378 379 while (1) 380 { 381 /* Create CVSADM. */ 382 (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM); 383 if ((CVS_MKDIR (tmp, 0777) < 0) && (errno != EEXIST)) 384 { 385 retval = errno; 386 goto finish; 387 } 388 389 /* Create CVSADM_REP. */ 390 (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_REP); 391 if (! isfile (tmp)) 392 { 393 /* Use Emptydir as the placeholder until the client sends 394 us the real value. This code is similar to checkout.c 395 (emptydir_name), but the code below returns errors 396 differently. */ 397 398 char *empty; 399 empty = malloc (strlen (current_parsed_root->directory) 400 + sizeof (CVSROOTADM) 401 + sizeof (CVSNULLREPOS) 402 + 3); 403 if (! empty) 404 { 405 retval = ENOMEM; 406 goto finish; 407 } 408 409 /* Create the directory name. */ 410 (void) sprintf (empty, "%s/%s/%s", current_parsed_root->directory, 411 CVSROOTADM, CVSNULLREPOS); 412 413 /* Create the directory if it doesn't exist. */ 414 if (! isfile (empty)) 415 { 416 mode_t omask; 417 omask = umask (cvsumask); 418 if (CVS_MKDIR (empty, 0777) < 0) 419 { 420 retval = errno; 421 free (empty); 422 goto finish; 423 } 424 (void) umask (omask); 425 } 426 427 428 f = CVS_FOPEN (tmp, "w"); 429 if (f == NULL) 430 { 431 retval = errno; 432 free (empty); 433 goto finish; 434 } 435 /* Write the directory name to CVSADM_REP. */ 436 if (fprintf (f, "%s\n", empty) < 0) 437 { 438 retval = errno; 439 fclose (f); 440 free (empty); 441 goto finish; 442 } 443 if (fclose (f) == EOF) 444 { 445 retval = errno; 446 free (empty); 447 goto finish; 448 } 449 450 /* Clean up after ourselves. */ 451 free (empty); 452 } 453 454 /* Create CVSADM_ENT. We open in append mode because we 455 don't want to clobber an existing Entries file. */ 456 (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_ENT); 457 f = CVS_FOPEN (tmp, "a"); 458 if (f == NULL) 459 { 460 retval = errno; 461 goto finish; 462 } 463 if (fclose (f) == EOF) 464 { 465 retval = errno; 466 goto finish; 467 } 468 469 if (dir_to_register != NULL) 470 { 471 /* FIXME: Yes, this results in duplicate entries in the 472 Entries.Log file, but it doesn't currently matter. We 473 might need to change this later on to make sure that we 474 only write one entry. */ 475 476 Subdir_Register ((List *) NULL, dir_where_cvsadm_lives, 477 dir_to_register); 478 } 479 480 if (done) 481 break; 482 483 dir_to_register = strrchr (p, '/'); 484 if (dir_to_register == NULL) 485 { 486 dir_to_register = p; 487 strcpy (dir_where_cvsadm_lives, base_dir); 488 done = 1; 489 } 490 else 491 { 492 *dir_to_register = '\0'; 493 dir_to_register++; 494 strcpy (dir_where_cvsadm_lives, base_dir); 495 strcat (dir_where_cvsadm_lives, "/"); 496 strcat (dir_where_cvsadm_lives, p); 497 } 498 } 499 500 finish: 501 free (tmp); 502 free (dir_where_cvsadm_lives); 503 free (p); 504 return retval; 505 } 506 507 /* 508 * Make directory DIR, including all intermediate directories if necessary. 509 * Returns 0 for success or errno code. 510 */ 511 static int mkdir_p PROTO((char *)); 512 513 static int 514 mkdir_p (dir) 515 char *dir; 516 { 517 char *p; 518 char *q = malloc (strlen (dir) + 1); 519 int retval; 520 521 if (q == NULL) 522 return ENOMEM; 523 524 retval = 0; 525 526 /* 527 * Skip over leading slash if present. We won't bother to try to 528 * make '/'. 529 */ 530 p = dir + 1; 531 while (1) 532 { 533 while (*p != '/' && *p != '\0') 534 ++p; 535 if (*p == '/') 536 { 537 strncpy (q, dir, p - dir); 538 q[p - dir] = '\0'; 539 if (q[p - dir - 1] != '/' && CVS_MKDIR (q, 0777) < 0) 540 { 541 int saved_errno = errno; 542 543 if (saved_errno != EEXIST 544 && ((saved_errno != EACCES && saved_errno != EROFS) 545 || !isdir (q))) 546 { 547 retval = saved_errno; 548 goto done; 549 } 550 } 551 ++p; 552 } 553 else 554 { 555 if (CVS_MKDIR (dir, 0777) < 0) 556 retval = errno; 557 goto done; 558 } 559 } 560 done: 561 free (q); 562 return retval; 563 } 564 565 /* 566 * Print the error response for error code STATUS. The caller is 567 * reponsible for making sure we get back to the command loop without 568 * any further output occuring. 569 * Must be called only in contexts where it is OK to send output. 570 */ 571 static void 572 print_error (status) 573 int status; 574 { 575 char *msg; 576 char tmpstr[80]; 577 578 buf_output0 (buf_to_net, "error "); 579 msg = strerror (status); 580 if (msg == NULL) 581 { 582 sprintf (tmpstr, "unknown error %d", status); 583 msg = tmpstr; 584 } 585 buf_output0 (buf_to_net, msg); 586 buf_append_char (buf_to_net, '\n'); 587 588 buf_flush (buf_to_net, 0); 589 } 590 591 static int pending_error; 592 /* 593 * Malloc'd text for pending error. Each line must start with "E ". The 594 * last line should not end with a newline. 595 */ 596 static char *pending_error_text; 597 598 /* If an error is pending, print it and return 1. If not, return 0. 599 Must be called only in contexts where it is OK to send output. */ 600 static int 601 print_pending_error () 602 { 603 if (pending_error_text) 604 { 605 buf_output0 (buf_to_net, pending_error_text); 606 buf_append_char (buf_to_net, '\n'); 607 if (pending_error) 608 print_error (pending_error); 609 else 610 buf_output0 (buf_to_net, "error \n"); 611 612 buf_flush (buf_to_net, 0); 613 614 pending_error = 0; 615 free (pending_error_text); 616 pending_error_text = NULL; 617 return 1; 618 } 619 else if (pending_error) 620 { 621 print_error (pending_error); 622 pending_error = 0; 623 return 1; 624 } 625 else 626 return 0; 627 } 628 629 /* Is an error pending? */ 630 #define error_pending() (pending_error || pending_error_text) 631 632 static int alloc_pending PROTO ((size_t size)); 633 634 /* Allocate SIZE bytes for pending_error_text and return nonzero 635 if we could do it. */ 636 static int 637 alloc_pending (size) 638 size_t size; 639 { 640 if (error_pending ()) 641 /* Probably alloc_pending callers will have already checked for 642 this case. But we might as well handle it if they don't, I 643 guess. */ 644 return 0; 645 pending_error_text = malloc (size); 646 if (pending_error_text == NULL) 647 { 648 pending_error = ENOMEM; 649 return 0; 650 } 651 return 1; 652 } 653 654 static void serve_is_modified PROTO ((char *)); 655 656 static int supported_response PROTO ((char *)); 657 658 static int 659 supported_response (name) 660 char *name; 661 { 662 struct response *rs; 663 664 for (rs = responses; rs->name != NULL; ++rs) 665 if (strcmp (rs->name, name) == 0) 666 return rs->status == rs_supported; 667 error (1, 0, "internal error: testing support for unknown response?"); 668 /* NOTREACHED */ 669 return 0; 670 } 671 672 static void 673 serve_valid_responses (arg) 674 char *arg; 675 { 676 char *p = arg; 677 char *q; 678 struct response *rs; 679 do 680 { 681 q = strchr (p, ' '); 682 if (q != NULL) 683 *q++ = '\0'; 684 for (rs = responses; rs->name != NULL; ++rs) 685 { 686 if (strcmp (rs->name, p) == 0) 687 break; 688 } 689 if (rs->name == NULL) 690 /* 691 * It is a response we have never heard of (and thus never 692 * will want to use). So don't worry about it. 693 */ 694 ; 695 else 696 rs->status = rs_supported; 697 p = q; 698 } while (q != NULL); 699 for (rs = responses; rs->name != NULL; ++rs) 700 { 701 if (rs->status == rs_essential) 702 { 703 buf_output0 (buf_to_net, "E response `"); 704 buf_output0 (buf_to_net, rs->name); 705 buf_output0 (buf_to_net, "' not supported by client\nerror \n"); 706 707 /* FIXME: This call to buf_flush could conceivably 708 cause deadlock, as noted in server_cleanup. */ 709 buf_flush (buf_to_net, 1); 710 711 /* I'm doing this manually rather than via error_exit () 712 because I'm not sure whether we want to call server_cleanup. 713 Needs more investigation.... */ 714 715 #ifdef SYSTEM_CLEANUP 716 /* Hook for OS-specific behavior, for example socket subsystems on 717 NT and OS2 or dealing with windows and arguments on Mac. */ 718 SYSTEM_CLEANUP (); 719 #endif 720 721 exit (EXIT_FAILURE); 722 } 723 else if (rs->status == rs_optional) 724 rs->status = rs_not_supported; 725 } 726 } 727 728 static void 729 serve_root (arg) 730 char *arg; 731 { 732 char *env; 733 char *path; 734 735 if (error_pending()) return; 736 737 if (!isabsolute (arg)) 738 { 739 if (alloc_pending (80 + strlen (arg))) 740 sprintf (pending_error_text, 741 "E Root %s must be an absolute pathname", arg); 742 return; 743 } 744 745 /* Sending "Root" twice is illegal. 746 747 The other way to handle a duplicate Root requests would be as a 748 request to clear out all state and start over as if it was a 749 new connection. Doing this would cause interoperability 750 headaches, so it should be a different request, if there is 751 any reason why such a feature is needed. */ 752 if (current_parsed_root != NULL) 753 { 754 if (alloc_pending (80 + strlen (arg))) 755 sprintf (pending_error_text, 756 "E Protocol error: Duplicate Root request, for %s", arg); 757 return; 758 } 759 760 #ifdef AUTH_SERVER_SUPPORT 761 if (Pserver_Repos != NULL) 762 { 763 if (strcmp (Pserver_Repos, arg) != 0) 764 { 765 if (alloc_pending (80 + strlen (Pserver_Repos) + strlen (arg))) 766 /* The explicitness is to aid people who are writing clients. 767 I don't see how this information could help an 768 attacker. */ 769 sprintf (pending_error_text, "\ 770 E Protocol error: Root says \"%s\" but pserver says \"%s\"", 771 arg, Pserver_Repos); 772 } 773 } 774 #endif 775 776 if (current_parsed_root != NULL) 777 free_cvsroot_t (current_parsed_root); 778 current_parsed_root = local_cvsroot (arg); 779 780 /* For pserver, this will already have happened, and the call will do 781 nothing. But for rsh, we need to do it now. */ 782 parse_config (current_parsed_root->directory); 783 784 path = malloc (strlen (current_parsed_root->directory) 785 + sizeof (CVSROOTADM) 786 + 2); 787 if (path == NULL) 788 { 789 pending_error = ENOMEM; 790 return; 791 } 792 (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM); 793 if (readonlyfs == 0 && !isaccessible (path, R_OK | X_OK)) 794 { 795 int save_errno = errno; 796 if (alloc_pending (80 + strlen (path))) 797 sprintf (pending_error_text, "E Cannot access %s", path); 798 pending_error = save_errno; 799 } 800 free (path); 801 802 #ifdef HAVE_PUTENV 803 env = malloc (strlen (CVSROOT_ENV) + strlen (current_parsed_root->directory) + 2); 804 if (env == NULL) 805 { 806 pending_error = ENOMEM; 807 return; 808 } 809 (void) sprintf (env, "%s=%s", CVSROOT_ENV, current_parsed_root->directory); 810 (void) putenv (env); 811 /* do not free env, as putenv has control of it */ 812 #endif 813 } 814 815 static int max_dotdot_limit = 0; 816 817 /* Is this pathname OK to recurse into when we are running as the server? 818 If not, call error() with a fatal error. */ 819 void 820 server_pathname_check (path) 821 char *path; 822 { 823 /* An absolute pathname is almost surely a path on the *client* machine, 824 and is unlikely to do us any good here. It also is probably capable 825 of being a security hole in the anonymous readonly case. */ 826 if (isabsolute (path)) 827 /* Giving an error is actually kind of a cop-out, in the sense 828 that it would be nice for "cvs co -d /foo/bar/baz" to work. 829 A quick fix in the server would be requiring Max-dotdot of 830 at least one if pathnames are absolute, and then putting 831 /abs/foo/bar/baz in the temp dir beside the /d/d/d stuff. 832 A cleaner fix in the server might be to decouple the 833 pathnames we pass back to the client from pathnames in our 834 temp directory (this would also probably remove the need 835 for Max-dotdot). A fix in the client would have the client 836 turn it into "cd /foo/bar; cvs co -d baz" (more or less). 837 This probably has some problems with pathnames which appear 838 in messages. */ 839 error (1, 0, "absolute pathname `%s' illegal for server", path); 840 if (pathname_levels (path) > max_dotdot_limit) 841 { 842 /* Similar to the isabsolute case in security implications. */ 843 error (0, 0, "protocol error: `%s' contains more leading ..", path); 844 error (1, 0, "than the %d which Max-dotdot specified", 845 max_dotdot_limit); 846 } 847 } 848 849 static int outside_root PROTO ((char *)); 850 851 /* Is file or directory REPOS an absolute pathname within the 852 current_parsed_root->directory? If yes, return 0. If no, set pending_error 853 and return 1. */ 854 static int 855 outside_root (repos) 856 char *repos; 857 { 858 size_t repos_len = strlen (repos); 859 size_t root_len = strlen (current_parsed_root->directory); 860 861 /* I think isabsolute (repos) should always be true, and that 862 any RELATIVE_REPOS stuff should only be in CVS/Repository 863 files, not the protocol (for compatibility), but I'm putting 864 in the isabsolute check just in case. */ 865 if (!isabsolute (repos)) 866 { 867 if (alloc_pending (repos_len + 80)) 868 sprintf (pending_error_text, "\ 869 E protocol error: %s is not absolute", repos); 870 return 1; 871 } 872 873 if (repos_len < root_len 874 || strncmp (current_parsed_root->directory, repos, root_len) != 0) 875 { 876 not_within: 877 if (alloc_pending (strlen (current_parsed_root->directory) 878 + strlen (repos) 879 + 80)) 880 sprintf (pending_error_text, "\ 881 E protocol error: directory '%s' not within root '%s'", 882 repos, current_parsed_root->directory); 883 return 1; 884 } 885 if (repos_len > root_len) 886 { 887 if (repos[root_len] != '/') 888 goto not_within; 889 if (pathname_levels (repos + root_len + 1) > 0) 890 goto not_within; 891 } 892 return 0; 893 } 894 895 static int outside_dir PROTO ((char *)); 896 897 /* Is file or directory FILE outside the current directory (that is, does 898 it contain '/')? If no, return 0. If yes, set pending_error 899 and return 1. */ 900 static int 901 outside_dir (file) 902 char *file; 903 { 904 if (strchr (file, '/') != NULL) 905 { 906 if (alloc_pending (strlen (file) 907 + 80)) 908 sprintf (pending_error_text, "\ 909 E protocol error: directory '%s' not within current directory", 910 file); 911 return 1; 912 } 913 return 0; 914 } 915 916 /* 917 * Add as many directories to the temp directory as the client tells us it 918 * will use "..", so we never try to access something outside the temp 919 * directory via "..". 920 */ 921 static void 922 serve_max_dotdot (arg) 923 char *arg; 924 { 925 int lim = atoi (arg); 926 int i; 927 char *p; 928 929 if (lim < 0) 930 return; 931 p = malloc (strlen (server_temp_dir) + 2 * lim + 10); 932 if (p == NULL) 933 { 934 pending_error = ENOMEM; 935 return; 936 } 937 strcpy (p, server_temp_dir); 938 for (i = 0; i < lim; ++i) 939 strcat (p, "/d"); 940 if (server_temp_dir != orig_server_temp_dir) 941 free (server_temp_dir); 942 server_temp_dir = p; 943 max_dotdot_limit = lim; 944 } 945 946 static char *dir_name; 947 948 static void 949 dirswitch (dir, repos) 950 char *dir; 951 char *repos; 952 { 953 int status; 954 FILE *f; 955 size_t dir_len; 956 957 server_write_entries (); 958 959 if (error_pending()) return; 960 961 /* Check for bad directory name. 962 963 FIXME: could/should unify these checks with server_pathname_check 964 except they need to report errors differently. */ 965 if (isabsolute (dir)) 966 { 967 if (alloc_pending (80 + strlen (dir))) 968 sprintf (pending_error_text, 969 "E absolute pathname `%s' illegal for server", dir); 970 return; 971 } 972 if (pathname_levels (dir) > max_dotdot_limit) 973 { 974 if (alloc_pending (80 + strlen (dir))) 975 sprintf (pending_error_text, 976 "E protocol error: `%s' has too many ..", dir); 977 return; 978 } 979 980 if (dir_name != NULL) 981 free (dir_name); 982 983 dir_len = strlen (dir); 984 985 /* Check for a trailing '/'. This is not ISDIRSEP because \ in the 986 protocol is an ordinary character, not a directory separator (of 987 course, it is perhaps unwise to use it in directory names, but that 988 is another issue). */ 989 if (dir_len > 0 990 && dir[dir_len - 1] == '/') 991 { 992 if (alloc_pending (80 + dir_len)) 993 sprintf (pending_error_text, 994 "E protocol error: invalid directory syntax in %s", dir); 995 return; 996 } 997 998 dir_name = malloc (strlen (server_temp_dir) + dir_len + 40); 999 if (dir_name == NULL) 1000 { 1001 pending_error = ENOMEM; 1002 return; 1003 } 1004 1005 strcpy (dir_name, server_temp_dir); 1006 strcat (dir_name, "/"); 1007 strcat (dir_name, dir); 1008 1009 status = mkdir_p (dir_name); 1010 if (status != 0 1011 && status != EEXIST) 1012 { 1013 if (alloc_pending (80 + strlen (dir_name))) 1014 sprintf (pending_error_text, "E cannot mkdir %s", dir_name); 1015 pending_error = status; 1016 return; 1017 } 1018 1019 /* We need to create adm directories in all path elements because 1020 we want the server to descend them, even if the client hasn't 1021 sent the appropriate "Argument xxx" command to match the 1022 already-sent "Directory xxx" command. See recurse.c 1023 (start_recursion) for a big discussion of this. */ 1024 1025 status = create_adm_p (server_temp_dir, dir); 1026 if (status != 0) 1027 { 1028 if (alloc_pending (80 + strlen (dir_name))) 1029 sprintf (pending_error_text, "E cannot create_adm_p %s", dir_name); 1030 pending_error = status; 1031 return; 1032 } 1033 1034 if ( CVS_CHDIR (dir_name) < 0) 1035 { 1036 int save_errno = errno; 1037 if (alloc_pending (80 + strlen (dir_name))) 1038 sprintf (pending_error_text, "E cannot change to %s", dir_name); 1039 pending_error = save_errno; 1040 return; 1041 } 1042 /* 1043 * This is pretty much like calling Create_Admin, but Create_Admin doesn't 1044 * report errors in the right way for us. 1045 */ 1046 if ((CVS_MKDIR (CVSADM, 0777) < 0) && (errno != EEXIST)) 1047 { 1048 int save_errno = errno; 1049 if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM))) 1050 sprintf (pending_error_text, 1051 "E cannot mkdir %s/%s", dir_name, CVSADM); 1052 pending_error = save_errno; 1053 return; 1054 } 1055 1056 /* The following will overwrite the contents of CVSADM_REP. This 1057 is the correct behavior -- mkdir_p may have written a 1058 placeholder value to this file and we need to insert the 1059 correct value. */ 1060 1061 f = CVS_FOPEN (CVSADM_REP, "w"); 1062 if (f == NULL) 1063 { 1064 int save_errno = errno; 1065 if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP))) 1066 sprintf (pending_error_text, 1067 "E cannot open %s/%s", dir_name, CVSADM_REP); 1068 pending_error = save_errno; 1069 return; 1070 } 1071 if (fprintf (f, "%s", repos) < 0) 1072 { 1073 int save_errno = errno; 1074 if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP))) 1075 sprintf (pending_error_text, 1076 "E error writing %s/%s", dir_name, CVSADM_REP); 1077 pending_error = save_errno; 1078 fclose (f); 1079 return; 1080 } 1081 /* Non-remote CVS handles a module representing the entire tree 1082 (e.g., an entry like ``world -a .'') by putting /. at the end 1083 of the Repository file, so we do the same. */ 1084 if (strcmp (dir, ".") == 0 1085 && current_parsed_root != NULL 1086 && current_parsed_root->directory != NULL 1087 && strcmp (current_parsed_root->directory, repos) == 0) 1088 { 1089 if (fprintf (f, "/.") < 0) 1090 { 1091 int save_errno = errno; 1092 if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP))) 1093 sprintf (pending_error_text, 1094 "E error writing %s/%s", dir_name, CVSADM_REP); 1095 pending_error = save_errno; 1096 fclose (f); 1097 return; 1098 } 1099 } 1100 if (fprintf (f, "\n") < 0) 1101 { 1102 int save_errno = errno; 1103 if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP))) 1104 sprintf (pending_error_text, 1105 "E error writing %s/%s", dir_name, CVSADM_REP); 1106 pending_error = save_errno; 1107 fclose (f); 1108 return; 1109 } 1110 if (fclose (f) == EOF) 1111 { 1112 int save_errno = errno; 1113 if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP))) 1114 sprintf (pending_error_text, 1115 "E error closing %s/%s", dir_name, CVSADM_REP); 1116 pending_error = save_errno; 1117 return; 1118 } 1119 /* We open in append mode because we don't want to clobber an 1120 existing Entries file. */ 1121 f = CVS_FOPEN (CVSADM_ENT, "a"); 1122 if (f == NULL) 1123 { 1124 int save_errno = errno; 1125 if (alloc_pending (80 + strlen (CVSADM_ENT))) 1126 sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT); 1127 pending_error = save_errno; 1128 return; 1129 } 1130 if (fclose (f) == EOF) 1131 { 1132 int save_errno = errno; 1133 if (alloc_pending (80 + strlen (CVSADM_ENT))) 1134 sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT); 1135 pending_error = save_errno; 1136 return; 1137 } 1138 } 1139 1140 static void 1141 serve_repository (arg) 1142 char *arg; 1143 { 1144 if (alloc_pending (80)) 1145 strcpy (pending_error_text, 1146 "E Repository request is obsolete; aborted"); 1147 return; 1148 } 1149 1150 static void 1151 serve_directory (arg) 1152 char *arg; 1153 { 1154 int status; 1155 char *repos; 1156 1157 status = buf_read_line (buf_from_net, &repos, (int *) NULL); 1158 if (status == 0) 1159 { 1160 if (!outside_root (repos)) 1161 dirswitch (arg, repos); 1162 free (repos); 1163 } 1164 else if (status == -2) 1165 { 1166 pending_error = ENOMEM; 1167 } 1168 else 1169 { 1170 pending_error_text = malloc (80 + strlen (arg)); 1171 if (pending_error_text == NULL) 1172 { 1173 pending_error = ENOMEM; 1174 } 1175 else if (status == -1) 1176 { 1177 sprintf (pending_error_text, 1178 "E end of file reading mode for %s", arg); 1179 } 1180 else 1181 { 1182 sprintf (pending_error_text, 1183 "E error reading mode for %s", arg); 1184 pending_error = status; 1185 } 1186 } 1187 } 1188 1189 static void 1190 serve_static_directory (arg) 1191 char *arg; 1192 { 1193 FILE *f; 1194 1195 if (error_pending ()) return; 1196 1197 f = CVS_FOPEN (CVSADM_ENTSTAT, "w+"); 1198 if (f == NULL) 1199 { 1200 int save_errno = errno; 1201 if (alloc_pending (80 + strlen (CVSADM_ENTSTAT))) 1202 sprintf (pending_error_text, "E cannot open %s", CVSADM_ENTSTAT); 1203 pending_error = save_errno; 1204 return; 1205 } 1206 if (fclose (f) == EOF) 1207 { 1208 int save_errno = errno; 1209 if (alloc_pending (80 + strlen (CVSADM_ENTSTAT))) 1210 sprintf (pending_error_text, "E cannot close %s", CVSADM_ENTSTAT); 1211 pending_error = save_errno; 1212 return; 1213 } 1214 } 1215 1216 static void 1217 serve_sticky (arg) 1218 char *arg; 1219 { 1220 FILE *f; 1221 1222 if (error_pending ()) return; 1223 1224 f = CVS_FOPEN (CVSADM_TAG, "w+"); 1225 if (f == NULL) 1226 { 1227 int save_errno = errno; 1228 if (alloc_pending (80 + strlen (CVSADM_TAG))) 1229 sprintf (pending_error_text, "E cannot open %s", CVSADM_TAG); 1230 pending_error = save_errno; 1231 return; 1232 } 1233 if (fprintf (f, "%s\n", arg) < 0) 1234 { 1235 int save_errno = errno; 1236 if (alloc_pending (80 + strlen (CVSADM_TAG))) 1237 sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG); 1238 pending_error = save_errno; 1239 return; 1240 } 1241 if (fclose (f) == EOF) 1242 { 1243 int save_errno = errno; 1244 if (alloc_pending (80 + strlen (CVSADM_TAG))) 1245 sprintf (pending_error_text, "E cannot close %s", CVSADM_TAG); 1246 pending_error = save_errno; 1247 return; 1248 } 1249 } 1250 1251 /* 1252 * Read SIZE bytes from buf_from_net, write them to FILE. 1253 * 1254 * Currently this isn't really used for receiving parts of a file -- 1255 * the file is still sent over in one chunk. But if/when we get 1256 * spiffy in-process gzip support working, perhaps the compressed 1257 * pieces could be sent over as they're ready, if the network is fast 1258 * enough. Or something. 1259 */ 1260 static void 1261 receive_partial_file (size, file) 1262 int size; 1263 int file; 1264 { 1265 while (size > 0) 1266 { 1267 int status, nread; 1268 char *data; 1269 1270 status = buf_read_data (buf_from_net, size, &data, &nread); 1271 if (status != 0) 1272 { 1273 if (status == -2) 1274 pending_error = ENOMEM; 1275 else 1276 { 1277 pending_error_text = malloc (80); 1278 if (pending_error_text == NULL) 1279 pending_error = ENOMEM; 1280 else if (status == -1) 1281 { 1282 sprintf (pending_error_text, 1283 "E premature end of file from client"); 1284 pending_error = 0; 1285 } 1286 else 1287 { 1288 sprintf (pending_error_text, 1289 "E error reading from client"); 1290 pending_error = status; 1291 } 1292 } 1293 return; 1294 } 1295 1296 size -= nread; 1297 1298 while (nread > 0) 1299 { 1300 int nwrote; 1301 1302 nwrote = write (file, data, nread); 1303 if (nwrote < 0) 1304 { 1305 int save_errno = errno; 1306 if (alloc_pending (40)) 1307 strcpy (pending_error_text, "E unable to write"); 1308 pending_error = save_errno; 1309 1310 /* Read and discard the file data. */ 1311 while (size > 0) 1312 { 1313 int status, nread; 1314 char *data; 1315 1316 status = buf_read_data (buf_from_net, size, &data, &nread); 1317 if (status != 0) 1318 return; 1319 size -= nread; 1320 } 1321 1322 return; 1323 } 1324 nread -= nwrote; 1325 data += nwrote; 1326 } 1327 } 1328 } 1329 1330 /* Receive SIZE bytes, write to filename FILE. */ 1331 static void 1332 receive_file (size, file, gzipped) 1333 int size; 1334 char *file; 1335 int gzipped; 1336 { 1337 int fd; 1338 char *arg = file; 1339 1340 /* Write the file. */ 1341 fd = CVS_OPEN (arg, O_WRONLY | O_CREAT | O_TRUNC, 0600); 1342 if (fd < 0) 1343 { 1344 int save_errno = errno; 1345 if (alloc_pending (40 + strlen (arg))) 1346 sprintf (pending_error_text, "E cannot open %s", arg); 1347 pending_error = save_errno; 1348 return; 1349 } 1350 1351 if (gzipped) 1352 { 1353 /* Using gunzip_and_write isn't really a high-performance 1354 approach, because it keeps the whole thing in memory 1355 (contiguous memory, worse yet). But it seems easier to 1356 code than the alternative (and less vulnerable to subtle 1357 bugs). Given that this feature is mainly for 1358 compatibility, that is the better tradeoff. */ 1359 1360 int toread = size; 1361 char *filebuf; 1362 char *p; 1363 1364 filebuf = malloc (size); 1365 p = filebuf; 1366 /* If NULL, we still want to read the data and discard it. */ 1367 1368 while (toread > 0) 1369 { 1370 int status, nread; 1371 char *data; 1372 1373 status = buf_read_data (buf_from_net, toread, &data, &nread); 1374 if (status != 0) 1375 { 1376 if (status == -2) 1377 pending_error = ENOMEM; 1378 else 1379 { 1380 pending_error_text = malloc (80); 1381 if (pending_error_text == NULL) 1382 pending_error = ENOMEM; 1383 else if (status == -1) 1384 { 1385 sprintf (pending_error_text, 1386 "E premature end of file from client"); 1387 pending_error = 0; 1388 } 1389 else 1390 { 1391 sprintf (pending_error_text, 1392 "E error reading from client"); 1393 pending_error = status; 1394 } 1395 } 1396 return; 1397 } 1398 1399 toread -= nread; 1400 1401 if (filebuf != NULL) 1402 { 1403 memcpy (p, data, nread); 1404 p += nread; 1405 } 1406 } 1407 if (filebuf == NULL) 1408 { 1409 pending_error = ENOMEM; 1410 goto out; 1411 } 1412 1413 if (gunzip_and_write (fd, file, (unsigned char *) filebuf, size)) 1414 { 1415 if (alloc_pending (80)) 1416 sprintf (pending_error_text, 1417 "E aborting due to compression error"); 1418 } 1419 free (filebuf); 1420 } 1421 else 1422 receive_partial_file (size, fd); 1423 1424 if (pending_error_text) 1425 { 1426 char *p = realloc (pending_error_text, 1427 strlen (pending_error_text) + strlen (arg) + 30); 1428 if (p) 1429 { 1430 pending_error_text = p; 1431 sprintf (p + strlen (p), ", file %s", arg); 1432 } 1433 /* else original string is supposed to be unchanged */ 1434 } 1435 1436 out: 1437 if (close (fd) < 0 && !error_pending ()) 1438 { 1439 int save_errno = errno; 1440 if (alloc_pending (40 + strlen (arg))) 1441 sprintf (pending_error_text, "E cannot close %s", arg); 1442 pending_error = save_errno; 1443 return; 1444 } 1445 } 1446 1447 /* Kopt for the next file sent in Modified or Is-modified. */ 1448 static char *kopt; 1449 1450 /* Timestamp (Checkin-time) for next file sent in Modified or 1451 Is-modified. */ 1452 static int checkin_time_valid; 1453 static time_t checkin_time; 1454 1455 static void serve_modified PROTO ((char *)); 1456 1457 static void 1458 serve_modified (arg) 1459 char *arg; 1460 { 1461 int size, status; 1462 char *size_text; 1463 char *mode_text; 1464 1465 int gzipped = 0; 1466 1467 /* 1468 * This used to return immediately if error_pending () was true. 1469 * However, that fails, because it causes each line of the file to 1470 * be echoed back to the client as an unrecognized command. The 1471 * client isn't reading from the socket, so eventually both 1472 * processes block trying to write to the other. Now, we try to 1473 * read the file if we can. 1474 */ 1475 1476 status = buf_read_line (buf_from_net, &mode_text, (int *) NULL); 1477 if (status != 0) 1478 { 1479 if (status == -2) 1480 pending_error = ENOMEM; 1481 else 1482 { 1483 pending_error_text = malloc (80 + strlen (arg)); 1484 if (pending_error_text == NULL) 1485 pending_error = ENOMEM; 1486 else 1487 { 1488 if (status == -1) 1489 sprintf (pending_error_text, 1490 "E end of file reading mode for %s", arg); 1491 else 1492 { 1493 sprintf (pending_error_text, 1494 "E error reading mode for %s", arg); 1495 pending_error = status; 1496 } 1497 } 1498 } 1499 return; 1500 } 1501 1502 status = buf_read_line (buf_from_net, &size_text, (int *) NULL); 1503 if (status != 0) 1504 { 1505 if (status == -2) 1506 pending_error = ENOMEM; 1507 else 1508 { 1509 pending_error_text = malloc (80 + strlen (arg)); 1510 if (pending_error_text == NULL) 1511 pending_error = ENOMEM; 1512 else 1513 { 1514 if (status == -1) 1515 sprintf (pending_error_text, 1516 "E end of file reading size for %s", arg); 1517 else 1518 { 1519 sprintf (pending_error_text, 1520 "E error reading size for %s", arg); 1521 pending_error = status; 1522 } 1523 } 1524 } 1525 free (mode_text); 1526 return; 1527 } 1528 if (size_text[0] == 'z') 1529 { 1530 gzipped = 1; 1531 size = atoi (size_text + 1); 1532 } 1533 else 1534 size = atoi (size_text); 1535 free (size_text); 1536 1537 if (error_pending ()) 1538 { 1539 /* Now that we know the size, read and discard the file data. */ 1540 while (size > 0) 1541 { 1542 int status, nread; 1543 char *data; 1544 1545 status = buf_read_data (buf_from_net, size, &data, &nread); 1546 if (status != 0) 1547 return; 1548 size -= nread; 1549 } 1550 free (mode_text); 1551 return; 1552 } 1553 1554 if (outside_dir (arg)) 1555 { 1556 free (mode_text); 1557 return; 1558 } 1559 1560 if (size >= 0) 1561 { 1562 receive_file (size, arg, gzipped); 1563 if (error_pending ()) 1564 { 1565 free (mode_text); 1566 return; 1567 } 1568 } 1569 1570 if (checkin_time_valid) 1571 { 1572 struct utimbuf t; 1573 1574 memset (&t, 0, sizeof (t)); 1575 t.modtime = t.actime = checkin_time; 1576 if (utime (arg, &t) < 0) 1577 { 1578 int save_errno = errno; 1579 if (alloc_pending (80 + strlen (arg))) 1580 sprintf (pending_error_text, "E cannot utime %s", arg); 1581 pending_error = save_errno; 1582 free (mode_text); 1583 return; 1584 } 1585 checkin_time_valid = 0; 1586 } 1587 1588 { 1589 int status = change_mode (arg, mode_text, 0); 1590 free (mode_text); 1591 if (status) 1592 { 1593 if (alloc_pending (40 + strlen (arg))) 1594 sprintf (pending_error_text, 1595 "E cannot change mode for %s", arg); 1596 pending_error = status; 1597 return; 1598 } 1599 } 1600 1601 /* Make sure that the Entries indicate the right kopt. We probably 1602 could do this even in the non-kopt case and, I think, save a stat() 1603 call in time_stamp_server. But for conservatism I'm leaving the 1604 non-kopt case alone. */ 1605 if (kopt != NULL) 1606 serve_is_modified (arg); 1607 } 1608 1609 1610 static void 1611 serve_enable_unchanged (arg) 1612 char *arg; 1613 { 1614 } 1615 1616 struct an_entry { 1617 struct an_entry *next; 1618 char *entry; 1619 }; 1620 1621 static struct an_entry *entries; 1622 1623 static void serve_unchanged PROTO ((char *)); 1624 1625 static void 1626 serve_unchanged (arg) 1627 char *arg; 1628 { 1629 struct an_entry *p; 1630 char *name; 1631 char *cp; 1632 char *timefield; 1633 1634 if (error_pending ()) 1635 return; 1636 1637 if (outside_dir (arg)) 1638 return; 1639 1640 /* Rewrite entries file to have `=' in timestamp field. */ 1641 for (p = entries; p != NULL; p = p->next) 1642 { 1643 name = p->entry + 1; 1644 cp = strchr (name, '/'); 1645 if (cp != NULL 1646 && strlen (arg) == cp - name 1647 && strncmp (arg, name, cp - name) == 0) 1648 { 1649 timefield = strchr (cp + 1, '/') + 1; 1650 if (*timefield != '=') 1651 { 1652 cp = timefield + strlen (timefield); 1653 cp[1] = '\0'; 1654 while (cp > timefield) 1655 { 1656 *cp = cp[-1]; 1657 --cp; 1658 } 1659 *timefield = '='; 1660 } 1661 break; 1662 } 1663 } 1664 } 1665 1666 static void 1667 serve_is_modified (arg) 1668 char *arg; 1669 { 1670 struct an_entry *p; 1671 char *name; 1672 char *cp; 1673 char *timefield; 1674 /* Have we found this file in "entries" yet. */ 1675 int found; 1676 1677 if (error_pending ()) 1678 return; 1679 1680 if (outside_dir (arg)) 1681 return; 1682 1683 /* Rewrite entries file to have `M' in timestamp field. */ 1684 found = 0; 1685 for (p = entries; p != NULL; p = p->next) 1686 { 1687 name = p->entry + 1; 1688 cp = strchr (name, '/'); 1689 if (cp != NULL 1690 && strlen (arg) == cp - name 1691 && strncmp (arg, name, cp - name) == 0) 1692 { 1693 timefield = strchr (cp + 1, '/') + 1; 1694 if (!(timefield[0] == 'M' && timefield[1] == '/')) 1695 { 1696 cp = timefield + strlen (timefield); 1697 cp[1] = '\0'; 1698 while (cp > timefield) 1699 { 1700 *cp = cp[-1]; 1701 --cp; 1702 } 1703 *timefield = 'M'; 1704 } 1705 if (kopt != NULL) 1706 { 1707 if (alloc_pending (strlen (name) + 80)) 1708 sprintf (pending_error_text, 1709 "E protocol error: both Kopt and Entry for %s", 1710 arg); 1711 free (kopt); 1712 kopt = NULL; 1713 return; 1714 } 1715 found = 1; 1716 break; 1717 } 1718 } 1719 if (!found) 1720 { 1721 /* We got Is-modified but no Entry. Add a dummy entry. 1722 The "D" timestamp is what makes it a dummy. */ 1723 p = (struct an_entry *) malloc (sizeof (struct an_entry)); 1724 if (p == NULL) 1725 { 1726 pending_error = ENOMEM; 1727 return; 1728 } 1729 p->entry = malloc (strlen (arg) + 80); 1730 if (p->entry == NULL) 1731 { 1732 pending_error = ENOMEM; 1733 free (p); 1734 return; 1735 } 1736 strcpy (p->entry, "/"); 1737 strcat (p->entry, arg); 1738 strcat (p->entry, "//D/"); 1739 if (kopt != NULL) 1740 { 1741 strcat (p->entry, kopt); 1742 free (kopt); 1743 kopt = NULL; 1744 } 1745 strcat (p->entry, "/"); 1746 p->next = entries; 1747 entries = p; 1748 } 1749 } 1750 1751 static void serve_entry PROTO ((char *)); 1752 1753 static void 1754 serve_entry (arg) 1755 char *arg; 1756 { 1757 struct an_entry *p; 1758 char *cp; 1759 if (error_pending()) return; 1760 p = (struct an_entry *) malloc (sizeof (struct an_entry)); 1761 if (p == NULL) 1762 { 1763 pending_error = ENOMEM; 1764 return; 1765 } 1766 /* Leave space for serve_unchanged to write '=' if it wants. */ 1767 cp = malloc (strlen (arg) + 2); 1768 if (cp == NULL) 1769 { 1770 pending_error = ENOMEM; 1771 return; 1772 } 1773 strcpy (cp, arg); 1774 p->next = entries; 1775 p->entry = cp; 1776 entries = p; 1777 } 1778 1779 static void serve_kopt PROTO ((char *)); 1780 1781 static void 1782 serve_kopt (arg) 1783 char *arg; 1784 { 1785 if (error_pending ()) 1786 return; 1787 1788 if (kopt != NULL) 1789 { 1790 if (alloc_pending (80 + strlen (arg))) 1791 sprintf (pending_error_text, 1792 "E protocol error: duplicate Kopt request: %s", arg); 1793 return; 1794 } 1795 1796 /* Do some sanity checks. In particular, that it is not too long. 1797 This lets the rest of the code not worry so much about buffer 1798 overrun attacks. Probably should call RCS_check_kflag here, 1799 but that would mean changing RCS_check_kflag to handle errors 1800 other than via exit(), fprintf(), and such. */ 1801 if (strlen (arg) > 10) 1802 { 1803 if (alloc_pending (80 + strlen (arg))) 1804 sprintf (pending_error_text, 1805 "E protocol error: invalid Kopt request: %s", arg); 1806 return; 1807 } 1808 1809 kopt = malloc (strlen (arg) + 1); 1810 if (kopt == NULL) 1811 { 1812 pending_error = ENOMEM; 1813 return; 1814 } 1815 strcpy (kopt, arg); 1816 } 1817 1818 static void serve_checkin_time PROTO ((char *)); 1819 1820 static void 1821 serve_checkin_time (arg) 1822 char *arg; 1823 { 1824 if (error_pending ()) 1825 return; 1826 1827 if (checkin_time_valid) 1828 { 1829 if (alloc_pending (80 + strlen (arg))) 1830 sprintf (pending_error_text, 1831 "E protocol error: duplicate Checkin-time request: %s", 1832 arg); 1833 return; 1834 } 1835 1836 checkin_time = get_date (arg, NULL); 1837 if (checkin_time == (time_t)-1) 1838 { 1839 if (alloc_pending (80 + strlen (arg))) 1840 sprintf (pending_error_text, "E cannot parse date %s", arg); 1841 return; 1842 } 1843 checkin_time_valid = 1; 1844 } 1845 1846 static void 1847 server_write_entries () 1848 { 1849 FILE *f; 1850 struct an_entry *p; 1851 struct an_entry *q; 1852 1853 if (entries == NULL) 1854 return; 1855 1856 f = NULL; 1857 /* Note that we free all the entries regardless of errors. */ 1858 if (!error_pending ()) 1859 { 1860 /* We open in append mode because we don't want to clobber an 1861 existing Entries file. If we are checking out a module 1862 which explicitly lists more than one file in a particular 1863 directory, then we will wind up calling 1864 server_write_entries for each such file. */ 1865 f = CVS_FOPEN (CVSADM_ENT, "a"); 1866 if (f == NULL) 1867 { 1868 int save_errno = errno; 1869 if (alloc_pending (80 + strlen (CVSADM_ENT))) 1870 sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT); 1871 pending_error = save_errno; 1872 } 1873 } 1874 for (p = entries; p != NULL;) 1875 { 1876 if (!error_pending ()) 1877 { 1878 if (fprintf (f, "%s\n", p->entry) < 0) 1879 { 1880 int save_errno = errno; 1881 if (alloc_pending (80 + strlen(CVSADM_ENT))) 1882 sprintf (pending_error_text, 1883 "E cannot write to %s", CVSADM_ENT); 1884 pending_error = save_errno; 1885 } 1886 } 1887 free (p->entry); 1888 q = p->next; 1889 free (p); 1890 p = q; 1891 } 1892 entries = NULL; 1893 if (f != NULL && fclose (f) == EOF && !error_pending ()) 1894 { 1895 int save_errno = errno; 1896 if (alloc_pending (80 + strlen (CVSADM_ENT))) 1897 sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT); 1898 pending_error = save_errno; 1899 } 1900 } 1901 1902 struct notify_note { 1903 /* Directory in which this notification happens. malloc'd*/ 1904 char *dir; 1905 1906 /* malloc'd. */ 1907 char *filename; 1908 1909 /* The following three all in one malloc'd block, pointed to by TYPE. 1910 Each '\0' terminated. */ 1911 /* "E" or "U". */ 1912 char *type; 1913 /* time+host+dir */ 1914 char *val; 1915 char *watches; 1916 1917 struct notify_note *next; 1918 }; 1919 1920 static struct notify_note *notify_list; 1921 /* Used while building list, to point to the last node that already exists. */ 1922 static struct notify_note *last_node; 1923 1924 static void serve_notify PROTO ((char *)); 1925 1926 static void 1927 serve_notify (arg) 1928 char *arg; 1929 { 1930 struct notify_note *new = NULL; 1931 char *data = NULL; 1932 int status; 1933 1934 if (error_pending ()) return; 1935 1936 if (outside_dir (arg)) 1937 return; 1938 1939 if (dir_name == NULL) 1940 goto error; 1941 1942 new = (struct notify_note *) malloc (sizeof (struct notify_note)); 1943 if (new == NULL) 1944 { 1945 pending_error = ENOMEM; 1946 return; 1947 } 1948 new->dir = malloc (strlen (dir_name) + 1); 1949 new->filename = malloc (strlen (arg) + 1); 1950 if (new->dir == NULL || new->filename == NULL) 1951 { 1952 pending_error = ENOMEM; 1953 if (new->dir != NULL) 1954 free (new->dir); 1955 free (new); 1956 return; 1957 } 1958 strcpy (new->dir, dir_name); 1959 strcpy (new->filename, arg); 1960 1961 status = buf_read_line (buf_from_net, &data, (int *) NULL); 1962 if (status != 0) 1963 { 1964 if (status == -2) 1965 pending_error = ENOMEM; 1966 else 1967 { 1968 pending_error_text = malloc (80 + strlen (arg)); 1969 if (pending_error_text == NULL) 1970 pending_error = ENOMEM; 1971 else 1972 { 1973 if (status == -1) 1974 sprintf (pending_error_text, 1975 "E end of file reading notification for %s", arg); 1976 else 1977 { 1978 sprintf (pending_error_text, 1979 "E error reading notification for %s", arg); 1980 pending_error = status; 1981 } 1982 } 1983 } 1984 free (new->filename); 1985 free (new->dir); 1986 free (new); 1987 } 1988 else 1989 { 1990 char *cp; 1991 1992 if (strchr (data, '+')) 1993 goto error; 1994 1995 new->type = data; 1996 if (data[1] != '\t') 1997 goto error; 1998 data[1] = '\0'; 1999 cp = data + 2; 2000 new->val = cp; 2001 cp = strchr (cp, '\t'); 2002 if (cp == NULL) 2003 goto error; 2004 *cp++ = '+'; 2005 cp = strchr (cp, '\t'); 2006 if (cp == NULL) 2007 goto error; 2008 *cp++ = '+'; 2009 cp = strchr (cp, '\t'); 2010 if (cp == NULL) 2011 goto error; 2012 *cp++ = '\0'; 2013 new->watches = cp; 2014 /* If there is another tab, ignore everything after it, 2015 for future expansion. */ 2016 cp = strchr (cp, '\t'); 2017 if (cp != NULL) 2018 { 2019 *cp = '\0'; 2020 } 2021 2022 new->next = NULL; 2023 2024 if (last_node == NULL) 2025 { 2026 notify_list = new; 2027 } 2028 else 2029 last_node->next = new; 2030 last_node = new; 2031 } 2032 return; 2033 error: 2034 pending_error = 0; 2035 if (alloc_pending (80)) 2036 strcpy (pending_error_text, 2037 "E Protocol error; misformed Notify request"); 2038 if (data != NULL) 2039 free (data); 2040 if (new != NULL) 2041 { 2042 free (new->filename); 2043 free (new->dir); 2044 free (new); 2045 } 2046 return; 2047 } 2048 2049 /* Process all the Notify requests that we have stored up. Returns 0 2050 if successful, if not prints error message (via error()) and 2051 returns negative value. */ 2052 static int 2053 server_notify () 2054 { 2055 struct notify_note *p; 2056 char *repos; 2057 2058 while (notify_list != NULL) 2059 { 2060 if ( CVS_CHDIR (notify_list->dir) < 0) 2061 { 2062 error (0, errno, "cannot change to %s", notify_list->dir); 2063 return -1; 2064 } 2065 repos = Name_Repository (NULL, NULL); 2066 2067 lock_dir_for_write (repos); 2068 2069 fileattr_startdir (repos); 2070 2071 notify_do (*notify_list->type, notify_list->filename, getcaller(), 2072 notify_list->val, notify_list->watches, repos); 2073 2074 buf_output0 (buf_to_net, "Notified "); 2075 { 2076 char *dir = notify_list->dir + strlen (server_temp_dir) + 1; 2077 if (dir[0] == '\0') 2078 buf_append_char (buf_to_net, '.'); 2079 else 2080 buf_output0 (buf_to_net, dir); 2081 buf_append_char (buf_to_net, '/'); 2082 buf_append_char (buf_to_net, '\n'); 2083 } 2084 buf_output0 (buf_to_net, repos); 2085 buf_append_char (buf_to_net, '/'); 2086 buf_output0 (buf_to_net, notify_list->filename); 2087 buf_append_char (buf_to_net, '\n'); 2088 free (repos); 2089 2090 p = notify_list->next; 2091 free (notify_list->filename); 2092 free (notify_list->dir); 2093 free (notify_list->type); 2094 free (notify_list); 2095 notify_list = p; 2096 2097 fileattr_write (); 2098 fileattr_free (); 2099 2100 Lock_Cleanup (); 2101 } 2102 2103 last_node = NULL; 2104 2105 /* The code used to call fflush (stdout) here, but that is no 2106 longer necessary. The data is now buffered in buf_to_net, 2107 which will be flushed by the caller, do_cvs_command. */ 2108 2109 return 0; 2110 } 2111 2112 static int argument_count; 2113 static char **argument_vector; 2114 static int argument_vector_size; 2115 2116 static void 2117 serve_argument (arg) 2118 char *arg; 2119 { 2120 char *p; 2121 2122 if (error_pending()) return; 2123 2124 if (argument_vector_size <= argument_count) 2125 { 2126 argument_vector_size *= 2; 2127 argument_vector = 2128 (char **) realloc ((char *)argument_vector, 2129 argument_vector_size * sizeof (char *)); 2130 if (argument_vector == NULL) 2131 { 2132 pending_error = ENOMEM; 2133 return; 2134 } 2135 } 2136 p = malloc (strlen (arg) + 1); 2137 if (p == NULL) 2138 { 2139 pending_error = ENOMEM; 2140 return; 2141 } 2142 strcpy (p, arg); 2143 argument_vector[argument_count++] = p; 2144 } 2145 2146 static void 2147 serve_argumentx (arg) 2148 char *arg; 2149 { 2150 char *p; 2151 2152 if (error_pending()) return; 2153 2154 p = argument_vector[argument_count - 1]; 2155 p = realloc (p, strlen (p) + 1 + strlen (arg) + 1); 2156 if (p == NULL) 2157 { 2158 pending_error = ENOMEM; 2159 return; 2160 } 2161 strcat (p, "\n"); 2162 strcat (p, arg); 2163 argument_vector[argument_count - 1] = p; 2164 } 2165 2166 static void 2167 serve_global_option (arg) 2168 char *arg; 2169 { 2170 if (arg[0] != '-' || arg[1] == '\0' || arg[2] != '\0') 2171 { 2172 error_return: 2173 if (alloc_pending (strlen (arg) + 80)) 2174 sprintf (pending_error_text, 2175 "E Protocol error: bad global option %s", 2176 arg); 2177 return; 2178 } 2179 switch (arg[1]) 2180 { 2181 case 'n': 2182 noexec = 1; 2183 break; 2184 case 'q': 2185 quiet = 1; 2186 break; 2187 case 'r': 2188 cvswrite = 0; 2189 break; 2190 case 'Q': 2191 really_quiet = 1; 2192 break; 2193 case 'l': 2194 logoff = 1; 2195 break; 2196 case 't': 2197 trace = 1; 2198 break; 2199 default: 2200 goto error_return; 2201 } 2202 } 2203 2204 static void 2205 serve_set (arg) 2206 char *arg; 2207 { 2208 /* FIXME: This sends errors immediately (I think); they should be 2209 put into pending_error. */ 2210 variable_set (arg); 2211 } 2212 2213 #ifdef ENCRYPTION 2214 2215 #ifdef HAVE_KERBEROS 2216 2217 static void 2218 serve_kerberos_encrypt (arg) 2219 char *arg; 2220 { 2221 /* All future communication with the client will be encrypted. */ 2222 2223 buf_to_net = krb_encrypt_buffer_initialize (buf_to_net, 0, sched, 2224 kblock, 2225 buf_to_net->memory_error); 2226 buf_from_net = krb_encrypt_buffer_initialize (buf_from_net, 1, sched, 2227 kblock, 2228 buf_from_net->memory_error); 2229 } 2230 2231 #endif /* HAVE_KERBEROS */ 2232 2233 #ifdef HAVE_GSSAPI 2234 2235 static void 2236 serve_gssapi_encrypt (arg) 2237 char *arg; 2238 { 2239 if (cvs_gssapi_wrapping) 2240 { 2241 /* We're already using a gssapi_wrap buffer for stream 2242 authentication. Flush everything we've output so far, and 2243 turn on encryption for future data. On the input side, we 2244 should only have unwrapped as far as the Gssapi-encrypt 2245 command, so future unwrapping will become encrypted. */ 2246 buf_flush (buf_to_net, 1); 2247 cvs_gssapi_encrypt = 1; 2248 return; 2249 } 2250 2251 /* All future communication with the client will be encrypted. */ 2252 2253 cvs_gssapi_encrypt = 1; 2254 2255 buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0, 2256 gcontext, 2257 buf_to_net->memory_error); 2258 buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1, 2259 gcontext, 2260 buf_from_net->memory_error); 2261 2262 cvs_gssapi_wrapping = 1; 2263 } 2264 2265 #endif /* HAVE_GSSAPI */ 2266 2267 #endif /* ENCRYPTION */ 2268 2269 #ifdef HAVE_GSSAPI 2270 2271 static void 2272 serve_gssapi_authenticate (arg) 2273 char *arg; 2274 { 2275 if (cvs_gssapi_wrapping) 2276 { 2277 /* We're already using a gssapi_wrap buffer for encryption. 2278 That includes authentication, so we don't have to do 2279 anything further. */ 2280 return; 2281 } 2282 2283 buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0, 2284 gcontext, 2285 buf_to_net->memory_error); 2286 buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1, 2287 gcontext, 2288 buf_from_net->memory_error); 2289 2290 cvs_gssapi_wrapping = 1; 2291 } 2292 2293 #endif /* HAVE_GSSAPI */ 2294 2295 #ifdef SERVER_FLOWCONTROL 2296 /* The maximum we'll queue to the remote client before blocking. */ 2297 # ifndef SERVER_HI_WATER 2298 # define SERVER_HI_WATER (2 * 1024 * 1024) 2299 # endif /* SERVER_HI_WATER */ 2300 /* When the buffer drops to this, we restart the child */ 2301 # ifndef SERVER_LO_WATER 2302 # define SERVER_LO_WATER (1 * 1024 * 1024) 2303 # endif /* SERVER_LO_WATER */ 2304 2305 static int set_nonblock_fd PROTO((int)); 2306 2307 /* 2308 * Set buffer BUF to non-blocking I/O. Returns 0 for success or errno 2309 * code. 2310 */ 2311 2312 static int 2313 set_nonblock_fd (fd) 2314 int fd; 2315 { 2316 int flags; 2317 2318 flags = fcntl (fd, F_GETFL, 0); 2319 if (flags < 0) 2320 return errno; 2321 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0) 2322 return errno; 2323 return 0; 2324 } 2325 2326 #endif /* SERVER_FLOWCONTROL */ 2327 2328 static void serve_questionable PROTO((char *)); 2329 2330 static void 2331 serve_questionable (arg) 2332 char *arg; 2333 { 2334 static int initted; 2335 2336 if (!initted) 2337 { 2338 /* Pick up ignores from CVSROOTADM_IGNORE, $HOME/.cvsignore on server, 2339 and CVSIGNORE on server. */ 2340 ign_setup (); 2341 initted = 1; 2342 } 2343 2344 if (dir_name == NULL) 2345 { 2346 buf_output0 (buf_to_net, "E Protocol error: 'Directory' missing"); 2347 return; 2348 } 2349 2350 if (outside_dir (arg)) 2351 return; 2352 2353 if (!ign_name (arg)) 2354 { 2355 char *update_dir; 2356 2357 buf_output (buf_to_net, "M ? ", 4); 2358 update_dir = dir_name + strlen (server_temp_dir) + 1; 2359 if (!(update_dir[0] == '.' && update_dir[1] == '\0')) 2360 { 2361 buf_output0 (buf_to_net, update_dir); 2362 buf_output (buf_to_net, "/", 1); 2363 } 2364 buf_output0 (buf_to_net, arg); 2365 buf_output (buf_to_net, "\n", 1); 2366 } 2367 } 2368 2369 static void serve_case PROTO ((char *)); 2370 2371 static void 2372 serve_case (arg) 2373 char *arg; 2374 { 2375 ign_case = 1; 2376 } 2377 2378 static struct buffer *protocol; 2379 2380 /* This is the output which we are saving up to send to the server, in the 2381 child process. We will push it through, via the `protocol' buffer, when 2382 we have a complete line. */ 2383 static struct buffer *saved_output; 2384 /* Likewise, but stuff which will go to stderr. */ 2385 static struct buffer *saved_outerr; 2386 2387 static void 2388 protocol_memory_error (buf) 2389 struct buffer *buf; 2390 { 2391 error (1, ENOMEM, "Virtual memory exhausted"); 2392 } 2393 2394 /* 2395 * Process IDs of the subprocess, or negative if that subprocess 2396 * does not exist. 2397 */ 2398 static pid_t command_pid; 2399 2400 static void 2401 outbuf_memory_error (buf) 2402 struct buffer *buf; 2403 { 2404 static const char msg[] = "E Fatal server error\n\ 2405 error ENOMEM Virtual memory exhausted.\n"; 2406 if (command_pid > 0) 2407 kill (command_pid, SIGTERM); 2408 2409 /* 2410 * We have arranged things so that printing this now either will 2411 * be legal, or the "E fatal error" line will get glommed onto the 2412 * end of an existing "E" or "M" response. 2413 */ 2414 2415 /* If this gives an error, not much we could do. syslog() it? */ 2416 write (STDOUT_FILENO, msg, sizeof (msg) - 1); 2417 #ifdef HAVE_SYSLOG_H 2418 syslog (LOG_DAEMON | LOG_ERR, "virtual memory exhausted"); 2419 #endif 2420 error_exit (); 2421 } 2422 2423 static void 2424 input_memory_error (buf) 2425 struct buffer *buf; 2426 { 2427 outbuf_memory_error (buf); 2428 } 2429 2430 2431 2432 /* If command is legal, return 1. 2433 * Else if command is illegal and croak_on_illegal is set, then die. 2434 * Else just return 0 to indicate that command is illegal. 2435 */ 2436 static int 2437 check_command_legal_p (cmd_name) 2438 char *cmd_name; 2439 { 2440 /* Right now, only pserver notices illegal commands -- namely, 2441 * write attempts by a read-only user. Therefore, if CVS_Username 2442 * is not set, this just returns 1, because CVS_Username unset 2443 * means pserver is not active. 2444 */ 2445 #ifdef AUTH_SERVER_SUPPORT 2446 if (CVS_Username == NULL) 2447 return 1; 2448 2449 if (lookup_command_attribute (cmd_name) & CVS_CMD_MODIFIES_REPOSITORY) 2450 { 2451 /* This command has the potential to modify the repository, so 2452 * we check if the user have permission to do that. 2453 * 2454 * (Only relevant for remote users -- local users can do 2455 * whatever normal Unix file permissions allow them to do.) 2456 * 2457 * The decision method: 2458 * 2459 * If $CVSROOT/CVSADMROOT_READERS exists and user is listed 2460 * in it, then read-only access for user. 2461 * 2462 * Or if $CVSROOT/CVSADMROOT_WRITERS exists and user NOT 2463 * listed in it, then also read-only access for user. 2464 * 2465 * Else read-write access for user. 2466 */ 2467 2468 char *linebuf = NULL; 2469 int num_red = 0; 2470 size_t linebuf_len = 0; 2471 char *fname; 2472 size_t flen; 2473 FILE *fp; 2474 int found_it = 0; 2475 2476 /* else */ 2477 flen = strlen (current_parsed_root->directory) 2478 + strlen (CVSROOTADM) 2479 + strlen (CVSROOTADM_READERS) 2480 + 3; 2481 2482 fname = xmalloc (flen); 2483 (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory, 2484 CVSROOTADM, CVSROOTADM_READERS); 2485 2486 fp = fopen (fname, "r"); 2487 2488 if (fp == NULL) 2489 { 2490 if (!existence_error (errno)) 2491 { 2492 /* Need to deny access, so that attackers can't fool 2493 us with some sort of denial of service attack. */ 2494 error (0, errno, "cannot open %s", fname); 2495 free (fname); 2496 return 0; 2497 } 2498 } 2499 else /* successfully opened readers file */ 2500 { 2501 while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0) 2502 { 2503 /* Hmmm, is it worth importing my own readline 2504 library into CVS? It takes care of chopping 2505 leading and trailing whitespace, "#" comments, and 2506 newlines automatically when so requested. Would 2507 save some code here... -kff */ 2508 2509 /* Chop newline by hand, for strcmp()'s sake. */ 2510 if (linebuf[num_red - 1] == '\n') 2511 linebuf[num_red - 1] = '\0'; 2512 2513 if (strcmp (linebuf, CVS_Username) == 0) 2514 goto handle_illegal; 2515 } 2516 if (num_red < 0 && !feof (fp)) 2517 error (0, errno, "cannot read %s", fname); 2518 2519 /* If not listed specifically as a reader, then this user 2520 has write access by default unless writers are also 2521 specified in a file . */ 2522 if (fclose (fp) < 0) 2523 error (0, errno, "cannot close %s", fname); 2524 } 2525 free (fname); 2526 2527 /* Now check the writers file. */ 2528 2529 flen = strlen (current_parsed_root->directory) 2530 + strlen (CVSROOTADM) 2531 + strlen (CVSROOTADM_WRITERS) 2532 + 3; 2533 2534 fname = xmalloc (flen); 2535 (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory, 2536 CVSROOTADM, CVSROOTADM_WRITERS); 2537 2538 fp = fopen (fname, "r"); 2539 2540 if (fp == NULL) 2541 { 2542 if (linebuf) 2543 free (linebuf); 2544 if (existence_error (errno)) 2545 { 2546 /* Writers file does not exist, so everyone is a writer, 2547 by default. */ 2548 free (fname); 2549 return 1; 2550 } 2551 else 2552 { 2553 /* Need to deny access, so that attackers can't fool 2554 us with some sort of denial of service attack. */ 2555 error (0, errno, "cannot read %s", fname); 2556 free (fname); 2557 return 0; 2558 } 2559 } 2560 2561 found_it = 0; 2562 while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0) 2563 { 2564 /* Chop newline by hand, for strcmp()'s sake. */ 2565 if (linebuf[num_red - 1] == '\n') 2566 linebuf[num_red - 1] = '\0'; 2567 2568 if (strcmp (linebuf, CVS_Username) == 0) 2569 { 2570 found_it = 1; 2571 break; 2572 } 2573 } 2574 if (num_red < 0 && !feof (fp)) 2575 error (0, errno, "cannot read %s", fname); 2576 2577 if (found_it) 2578 { 2579 if (fclose (fp) < 0) 2580 error (0, errno, "cannot close %s", fname); 2581 if (linebuf) 2582 free (linebuf); 2583 free (fname); 2584 return 1; 2585 } 2586 else /* writers file exists, but this user not listed in it */ 2587 { 2588 handle_illegal: 2589 if (fclose (fp) < 0) 2590 error (0, errno, "cannot close %s", fname); 2591 if (linebuf) 2592 free (linebuf); 2593 free (fname); 2594 return 0; 2595 } 2596 } 2597 #endif /* AUTH_SERVER_SUPPORT */ 2598 2599 /* If ever reach end of this function, command must be legal. */ 2600 return 1; 2601 } 2602 2603 2604 2605 /* Execute COMMAND in a subprocess with the approriate funky things done. */ 2606 2607 static struct fd_set_wrapper { fd_set fds; } command_fds_to_drain; 2608 static int max_command_fd; 2609 2610 #ifdef SERVER_FLOWCONTROL 2611 static int flowcontrol_pipe[2]; 2612 #endif /* SERVER_FLOWCONTROL */ 2613 2614 static void 2615 do_cvs_command (cmd_name, command) 2616 char *cmd_name; 2617 int (*command) PROTO((int argc, char **argv)); 2618 { 2619 /* 2620 * The following file descriptors are set to -1 if that file is not 2621 * currently open. 2622 */ 2623 2624 /* Data on these pipes is a series of '\n'-terminated lines. */ 2625 int stdout_pipe[2]; 2626 int stderr_pipe[2]; 2627 2628 /* 2629 * Data on this pipe is a series of counted (see buf_send_counted) 2630 * packets. Each packet must be processed atomically (i.e. not 2631 * interleaved with data from stdout_pipe or stderr_pipe). 2632 */ 2633 int protocol_pipe[2]; 2634 2635 int dev_null_fd = -1; 2636 2637 int errs; 2638 2639 command_pid = -1; 2640 stdout_pipe[0] = -1; 2641 stdout_pipe[1] = -1; 2642 stderr_pipe[0] = -1; 2643 stderr_pipe[1] = -1; 2644 protocol_pipe[0] = -1; 2645 protocol_pipe[1] = -1; 2646 2647 server_write_entries (); 2648 2649 if (print_pending_error ()) 2650 goto free_args_and_return; 2651 2652 /* Global `command_name' is probably "server" right now -- only 2653 serve_export() sets it to anything else. So we will use local 2654 parameter `cmd_name' to determine if this command is legal for 2655 this user. */ 2656 if (!check_command_legal_p (cmd_name)) 2657 { 2658 buf_output0 (buf_to_net, "E "); 2659 buf_output0 (buf_to_net, program_name); 2660 buf_output0 (buf_to_net, " [server aborted]: \""); 2661 buf_output0 (buf_to_net, cmd_name); 2662 buf_output0 (buf_to_net, "\" requires write access to the repository\n\ 2663 error \n"); 2664 goto free_args_and_return; 2665 } 2666 2667 (void) server_notify (); 2668 2669 /* 2670 * We use a child process which actually does the operation. This 2671 * is so we can intercept its standard output. Even if all of CVS 2672 * were written to go to some special routine instead of writing 2673 * to stdout or stderr, we would still need to do the same thing 2674 * for the RCS commands. 2675 */ 2676 2677 if (pipe (stdout_pipe) < 0) 2678 { 2679 buf_output0 (buf_to_net, "E pipe failed\n"); 2680 print_error (errno); 2681 goto error_exit; 2682 } 2683 if (pipe (stderr_pipe) < 0) 2684 { 2685 buf_output0 (buf_to_net, "E pipe failed\n"); 2686 print_error (errno); 2687 goto error_exit; 2688 } 2689 if (pipe (protocol_pipe) < 0) 2690 { 2691 buf_output0 (buf_to_net, "E pipe failed\n"); 2692 print_error (errno); 2693 goto error_exit; 2694 } 2695 #ifdef SERVER_FLOWCONTROL 2696 if (pipe (flowcontrol_pipe) < 0) 2697 { 2698 buf_output0 (buf_to_net, "E pipe failed\n"); 2699 print_error (errno); 2700 goto error_exit; 2701 } 2702 set_nonblock_fd (flowcontrol_pipe[0]); 2703 set_nonblock_fd (flowcontrol_pipe[1]); 2704 #endif /* SERVER_FLOWCONTROL */ 2705 2706 dev_null_fd = CVS_OPEN (DEVNULL, O_RDONLY); 2707 if (dev_null_fd < 0) 2708 { 2709 buf_output0 (buf_to_net, "E open /dev/null failed\n"); 2710 print_error (errno); 2711 goto error_exit; 2712 } 2713 2714 /* We shouldn't have any partial lines from cvs_output and 2715 cvs_outerr, but we handle them here in case there is a bug. */ 2716 /* FIXME: appending a newline, rather than using "MT" as we 2717 do in the child process, is probably not really a very good 2718 way to "handle" them. */ 2719 if (! buf_empty_p (saved_output)) 2720 { 2721 buf_append_char (saved_output, '\n'); 2722 buf_copy_lines (buf_to_net, saved_output, 'M'); 2723 } 2724 if (! buf_empty_p (saved_outerr)) 2725 { 2726 buf_append_char (saved_outerr, '\n'); 2727 buf_copy_lines (buf_to_net, saved_outerr, 'E'); 2728 } 2729 2730 /* Flush out any pending data. */ 2731 buf_flush (buf_to_net, 1); 2732 2733 /* Don't use vfork; we're not going to exec(). */ 2734 command_pid = fork (); 2735 if (command_pid < 0) 2736 { 2737 buf_output0 (buf_to_net, "E fork failed\n"); 2738 print_error (errno); 2739 goto error_exit; 2740 } 2741 if (command_pid == 0) 2742 { 2743 int exitstatus; 2744 2745 /* Since we're in the child, and the parent is going to take 2746 care of packaging up our error messages, we can clear this 2747 flag. */ 2748 error_use_protocol = 0; 2749 2750 protocol = fd_buffer_initialize (protocol_pipe[1], 0, 2751 protocol_memory_error); 2752 2753 /* At this point we should no longer be using buf_to_net and 2754 buf_from_net. Instead, everything should go through 2755 protocol. */ 2756 buf_to_net = NULL; 2757 buf_from_net = NULL; 2758 2759 /* These were originally set up to use outbuf_memory_error. 2760 Since we're now in the child, we should use the simpler 2761 protocol_memory_error function. */ 2762 saved_output->memory_error = protocol_memory_error; 2763 saved_outerr->memory_error = protocol_memory_error; 2764 2765 if (dup2 (dev_null_fd, STDIN_FILENO) < 0) 2766 error (1, errno, "can't set up pipes"); 2767 if (dup2 (stdout_pipe[1], STDOUT_FILENO) < 0) 2768 error (1, errno, "can't set up pipes"); 2769 if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0) 2770 error (1, errno, "can't set up pipes"); 2771 close (dev_null_fd); 2772 close (stdout_pipe[0]); 2773 close (stdout_pipe[1]); 2774 close (stderr_pipe[0]); 2775 close (stderr_pipe[1]); 2776 close (protocol_pipe[0]); 2777 close_on_exec (protocol_pipe[1]); 2778 #ifdef SERVER_FLOWCONTROL 2779 close_on_exec (flowcontrol_pipe[0]); 2780 close (flowcontrol_pipe[1]); 2781 #endif /* SERVER_FLOWCONTROL */ 2782 2783 /* 2784 * Set this in .bashrc if you want to give yourself time to attach 2785 * to the subprocess with a debugger. 2786 */ 2787 if (getenv ("CVS_SERVER_SLEEP")) 2788 { 2789 int secs = atoi (getenv ("CVS_SERVER_SLEEP")); 2790 sleep (secs); 2791 } 2792 2793 exitstatus = (*command) (argument_count, argument_vector); 2794 2795 /* Output any partial lines. If the client doesn't support 2796 "MT", we go ahead and just tack on a newline since the 2797 protocol doesn't support anything better. */ 2798 if (! buf_empty_p (saved_output)) 2799 { 2800 buf_output0 (protocol, supported_response ("MT") ? "MT text " : "M "); 2801 buf_append_buffer (protocol, saved_output); 2802 buf_output (protocol, "\n", 1); 2803 buf_send_counted (protocol); 2804 } 2805 /* For now we just discard partial lines on stderr. I suspect 2806 that CVS can't write such lines unless there is a bug. */ 2807 2808 /* 2809 * When we exit, that will close the pipes, giving an EOF to 2810 * the parent. 2811 */ 2812 buf_free (protocol); 2813 exit (exitstatus); 2814 } 2815 2816 /* OK, sit around getting all the input from the child. */ 2817 { 2818 struct buffer *stdoutbuf; 2819 struct buffer *stderrbuf; 2820 struct buffer *protocol_inbuf; 2821 /* Number of file descriptors to check in select (). */ 2822 int num_to_check; 2823 int count_needed = 1; 2824 #ifdef SERVER_FLOWCONTROL 2825 int have_flowcontrolled = 0; 2826 #endif /* SERVER_FLOWCONTROL */ 2827 2828 FD_ZERO (&command_fds_to_drain.fds); 2829 num_to_check = stdout_pipe[0]; 2830 FD_SET (stdout_pipe[0], &command_fds_to_drain.fds); 2831 if (stderr_pipe[0] > num_to_check) 2832 num_to_check = stderr_pipe[0]; 2833 FD_SET (stderr_pipe[0], &command_fds_to_drain.fds); 2834 if (protocol_pipe[0] > num_to_check) 2835 num_to_check = protocol_pipe[0]; 2836 FD_SET (protocol_pipe[0], &command_fds_to_drain.fds); 2837 if (STDOUT_FILENO > num_to_check) 2838 num_to_check = STDOUT_FILENO; 2839 max_command_fd = num_to_check; 2840 /* 2841 * File descriptors are numbered from 0, so num_to_check needs to 2842 * be one larger than the largest descriptor. 2843 */ 2844 ++num_to_check; 2845 if (num_to_check > FD_SETSIZE) 2846 { 2847 buf_output0 (buf_to_net, 2848 "E internal error: FD_SETSIZE not big enough.\n\ 2849 error \n"); 2850 goto error_exit; 2851 } 2852 2853 stdoutbuf = fd_buffer_initialize (stdout_pipe[0], 1, 2854 input_memory_error); 2855 2856 stderrbuf = fd_buffer_initialize (stderr_pipe[0], 1, 2857 input_memory_error); 2858 2859 protocol_inbuf = fd_buffer_initialize (protocol_pipe[0], 1, 2860 input_memory_error); 2861 2862 set_nonblock (buf_to_net); 2863 set_nonblock (stdoutbuf); 2864 set_nonblock (stderrbuf); 2865 set_nonblock (protocol_inbuf); 2866 2867 if (close (stdout_pipe[1]) < 0) 2868 { 2869 buf_output0 (buf_to_net, "E close failed\n"); 2870 print_error (errno); 2871 goto error_exit; 2872 } 2873 stdout_pipe[1] = -1; 2874 2875 if (close (stderr_pipe[1]) < 0) 2876 { 2877 buf_output0 (buf_to_net, "E close failed\n"); 2878 print_error (errno); 2879 goto error_exit; 2880 } 2881 stderr_pipe[1] = -1; 2882 2883 if (close (protocol_pipe[1]) < 0) 2884 { 2885 buf_output0 (buf_to_net, "E close failed\n"); 2886 print_error (errno); 2887 goto error_exit; 2888 } 2889 protocol_pipe[1] = -1; 2890 2891 #ifdef SERVER_FLOWCONTROL 2892 if (close (flowcontrol_pipe[0]) < 0) 2893 { 2894 buf_output0 (buf_to_net, "E close failed\n"); 2895 print_error (errno); 2896 goto error_exit; 2897 } 2898 flowcontrol_pipe[0] = -1; 2899 #endif /* SERVER_FLOWCONTROL */ 2900 2901 if (close (dev_null_fd) < 0) 2902 { 2903 buf_output0 (buf_to_net, "E close failed\n"); 2904 print_error (errno); 2905 goto error_exit; 2906 } 2907 dev_null_fd = -1; 2908 2909 while (stdout_pipe[0] >= 0 2910 || stderr_pipe[0] >= 0 2911 || protocol_pipe[0] >= 0 2912 || count_needed <= 0) 2913 { 2914 fd_set readfds; 2915 fd_set writefds; 2916 int numfds; 2917 #ifdef SERVER_FLOWCONTROL 2918 int bufmemsize; 2919 struct timeval *timeout_ptr; 2920 struct timeval timeout; 2921 2922 /* 2923 * See if we are swamping the remote client and filling our VM. 2924 * Tell child to hold off if we do. 2925 */ 2926 bufmemsize = buf_count_mem (buf_to_net); 2927 if (!have_flowcontrolled && (bufmemsize > SERVER_HI_WATER)) 2928 { 2929 if (write(flowcontrol_pipe[1], "S", 1) == 1) 2930 have_flowcontrolled = 1; 2931 } 2932 else if (have_flowcontrolled && (bufmemsize < SERVER_LO_WATER)) 2933 { 2934 if (write(flowcontrol_pipe[1], "G", 1) == 1) 2935 have_flowcontrolled = 0; 2936 } 2937 #endif /* SERVER_FLOWCONTROL */ 2938 2939 FD_ZERO (&readfds); 2940 FD_ZERO (&writefds); 2941 2942 if (count_needed <= 0) 2943 { 2944 /* there is data pending which was read from the protocol pipe 2945 * so don't block if we don't find any data 2946 */ 2947 timeout.tv_sec = 0; 2948 timeout.tv_usec = 0; 2949 timeout_ptr = &timeout; 2950 } 2951 else 2952 { 2953 /* block indefinately */ 2954 timeout_ptr = NULL; 2955 } 2956 2957 if (! buf_empty_p (buf_to_net)) 2958 FD_SET (STDOUT_FILENO, &writefds); 2959 2960 if (stdout_pipe[0] >= 0) 2961 { 2962 FD_SET (stdout_pipe[0], &readfds); 2963 } 2964 if (stderr_pipe[0] >= 0) 2965 { 2966 FD_SET (stderr_pipe[0], &readfds); 2967 } 2968 if (protocol_pipe[0] >= 0) 2969 { 2970 FD_SET (protocol_pipe[0], &readfds); 2971 } 2972 2973 /* This process of selecting on the three pipes means that 2974 we might not get output in the same order in which it 2975 was written, thus producing the well-known 2976 "out-of-order" bug. If the child process uses 2977 cvs_output and cvs_outerr, it will send everything on 2978 the protocol_pipe and avoid this problem, so the 2979 solution is to use cvs_output and cvs_outerr in the 2980 child process. */ 2981 do { 2982 /* This used to select on exceptions too, but as far 2983 as I know there was never any reason to do that and 2984 SCO doesn't let you select on exceptions on pipes. */ 2985 numfds = select (num_to_check, &readfds, &writefds, 2986 (fd_set *)0, timeout_ptr); 2987 if (numfds < 0 2988 && errno != EINTR) 2989 { 2990 buf_output0 (buf_to_net, "E select failed\n"); 2991 print_error (errno); 2992 goto error_exit; 2993 } 2994 } while (numfds < 0); 2995 2996 if (numfds == 0) 2997 { 2998 FD_ZERO (&readfds); 2999 FD_ZERO (&writefds); 3000 } 3001 3002 if (FD_ISSET (STDOUT_FILENO, &writefds)) 3003 { 3004 /* What should we do with errors? syslog() them? */ 3005 buf_send_output (buf_to_net); 3006 } 3007 3008 if (protocol_pipe[0] >= 0 3009 && (FD_ISSET (protocol_pipe[0], &readfds))) 3010 { 3011 int status; 3012 int count_read; 3013 3014 status = buf_input_data (protocol_inbuf, &count_read); 3015 3016 if (status == -1) 3017 { 3018 close (protocol_pipe[0]); 3019 protocol_pipe[0] = -1; 3020 } 3021 else if (status > 0) 3022 { 3023 buf_output0 (buf_to_net, "E buf_input_data failed\n"); 3024 print_error (status); 3025 goto error_exit; 3026 } 3027 3028 /* 3029 * We only call buf_copy_counted if we have read 3030 * enough bytes to make it worthwhile. This saves us 3031 * from continually recounting the amount of data we 3032 * have. 3033 */ 3034 count_needed -= count_read; 3035 } 3036 /* this is still part of the protocol pipe procedure, but it is 3037 * outside the above conditional so that unprocessed data can be 3038 * left in the buffer and stderr/stdout can be read when a flush 3039 * signal is received and control can return here without passing 3040 * through the select code and maybe blocking 3041 */ 3042 while (count_needed <= 0) 3043 { 3044 int special = 0; 3045 3046 count_needed = buf_copy_counted (buf_to_net, 3047 protocol_inbuf, 3048 &special); 3049 3050 /* What should we do with errors? syslog() them? */ 3051 buf_send_output (buf_to_net); 3052 3053 /* If SPECIAL got set to <0, it means that the child 3054 * wants us to flush the pipe & maybe stderr or stdout. 3055 * 3056 * After that we break to read stderr & stdout again before 3057 * going back to the protocol pipe 3058 * 3059 * Upon breaking, count_needed = 0, so the next pass will only 3060 * perform a non-blocking select before returning here to finish 3061 * processing data we already read from the protocol buffer 3062 */ 3063 if (special == -1) 3064 { 3065 cvs_flushout(); 3066 break; 3067 } 3068 if (special == -2) 3069 { 3070 /* If the client supports the 'F' command, we send it. */ 3071 if (supported_response ("F")) 3072 { 3073 buf_append_char (buf_to_net, 'F'); 3074 buf_append_char (buf_to_net, '\n'); 3075 } 3076 cvs_flusherr (); 3077 break; 3078 } 3079 } 3080 3081 if (stdout_pipe[0] >= 0 3082 && (FD_ISSET (stdout_pipe[0], &readfds))) 3083 { 3084 int status; 3085 3086 status = buf_input_data (stdoutbuf, (int *) NULL); 3087 3088 buf_copy_lines (buf_to_net, stdoutbuf, 'M'); 3089 3090 if (status == -1) 3091 { 3092 close (stdout_pipe[0]); 3093 stdout_pipe[0] = -1; 3094 } 3095 else if (status > 0) 3096 { 3097 buf_output0 (buf_to_net, "E buf_input_data failed\n"); 3098 print_error (status); 3099 goto error_exit; 3100 } 3101 3102 /* What should we do with errors? syslog() them? */ 3103 buf_send_output (buf_to_net); 3104 } 3105 3106 if (stderr_pipe[0] >= 0 3107 && (FD_ISSET (stderr_pipe[0], &readfds))) 3108 { 3109 int status; 3110 3111 status = buf_input_data (stderrbuf, (int *) NULL); 3112 3113 buf_copy_lines (buf_to_net, stderrbuf, 'E'); 3114 3115 if (status == -1) 3116 { 3117 close (stderr_pipe[0]); 3118 stderr_pipe[0] = -1; 3119 } 3120 else if (status > 0) 3121 { 3122 buf_output0 (buf_to_net, "E buf_input_data failed\n"); 3123 print_error (status); 3124 goto error_exit; 3125 } 3126 3127 /* What should we do with errors? syslog() them? */ 3128 buf_send_output (buf_to_net); 3129 } 3130 } 3131 3132 /* 3133 * OK, we've gotten EOF on all the pipes. If there is 3134 * anything left on stdoutbuf or stderrbuf (this could only 3135 * happen if there was no trailing newline), send it over. 3136 */ 3137 if (! buf_empty_p (stdoutbuf)) 3138 { 3139 buf_append_char (stdoutbuf, '\n'); 3140 buf_copy_lines (buf_to_net, stdoutbuf, 'M'); 3141 } 3142 if (! buf_empty_p (stderrbuf)) 3143 { 3144 buf_append_char (stderrbuf, '\n'); 3145 buf_copy_lines (buf_to_net, stderrbuf, 'E'); 3146 } 3147 if (! buf_empty_p (protocol_inbuf)) 3148 buf_output0 (buf_to_net, 3149 "E Protocol error: uncounted data discarded\n"); 3150 3151 #ifdef SERVER_FLOWCONTROL 3152 close (flowcontrol_pipe[1]); 3153 flowcontrol_pipe[1] = -1; 3154 #endif /* SERVER_FLOWCONTROL */ 3155 3156 errs = 0; 3157 3158 while (command_pid > 0) 3159 { 3160 int status; 3161 pid_t waited_pid; 3162 waited_pid = waitpid (command_pid, &status, 0); 3163 if (waited_pid < 0) 3164 { 3165 /* 3166 * Intentionally ignoring EINTR. Other errors 3167 * "can't happen". 3168 */ 3169 continue; 3170 } 3171 3172 if (WIFEXITED (status)) 3173 errs += WEXITSTATUS (status); 3174 else 3175 { 3176 int sig = WTERMSIG (status); 3177 char buf[50]; 3178 /* 3179 * This is really evil, because signals might be numbered 3180 * differently on the two systems. We should be using 3181 * signal names (either of the "Terminated" or the "SIGTERM" 3182 * variety). But cvs doesn't currently use libiberty...we 3183 * could roll our own.... FIXME. 3184 */ 3185 buf_output0 (buf_to_net, "E Terminated with fatal signal "); 3186 sprintf (buf, "%d\n", sig); 3187 buf_output0 (buf_to_net, buf); 3188 3189 /* Test for a core dump. Is this portable? */ 3190 if (status & 0x80) 3191 { 3192 buf_output0 (buf_to_net, "E Core dumped; preserving "); 3193 buf_output0 (buf_to_net, orig_server_temp_dir); 3194 buf_output0 (buf_to_net, " on server.\n\ 3195 E CVS locks may need cleaning up.\n"); 3196 dont_delete_temp = 1; 3197 } 3198 ++errs; 3199 } 3200 if (waited_pid == command_pid) 3201 command_pid = -1; 3202 } 3203 3204 /* 3205 * OK, we've waited for the child. By now all CVS locks are free 3206 * and it's OK to block on the network. 3207 */ 3208 set_block (buf_to_net); 3209 buf_flush (buf_to_net, 1); 3210 buf_shutdown (protocol_inbuf); 3211 buf_free (protocol_inbuf); 3212 buf_shutdown (stderrbuf); 3213 buf_free (stderrbuf); 3214 buf_shutdown (stdoutbuf); 3215 buf_free (stdoutbuf); 3216 } 3217 3218 if (errs) 3219 /* We will have printed an error message already. */ 3220 buf_output0 (buf_to_net, "error \n"); 3221 else 3222 buf_output0 (buf_to_net, "ok\n"); 3223 goto free_args_and_return; 3224 3225 error_exit: 3226 if (command_pid > 0) 3227 kill (command_pid, SIGTERM); 3228 3229 while (command_pid > 0) 3230 { 3231 pid_t waited_pid; 3232 waited_pid = waitpid (command_pid, (int *) 0, 0); 3233 if (waited_pid < 0 && errno == EINTR) 3234 continue; 3235 if (waited_pid == command_pid) 3236 command_pid = -1; 3237 } 3238 3239 close (dev_null_fd); 3240 close (protocol_pipe[0]); 3241 close (protocol_pipe[1]); 3242 close (stderr_pipe[0]); 3243 close (stderr_pipe[1]); 3244 close (stdout_pipe[0]); 3245 close (stdout_pipe[1]); 3246 #ifdef SERVER_FLOWCONTROL 3247 close (flowcontrol_pipe[0]); 3248 close (flowcontrol_pipe[1]); 3249 #endif /* SERVER_FLOWCONTROL */ 3250 3251 free_args_and_return: 3252 /* Now free the arguments. */ 3253 { 3254 /* argument_vector[0] is a dummy argument, we don't mess with it. */ 3255 char **cp; 3256 for (cp = argument_vector + 1; 3257 cp < argument_vector + argument_count; 3258 ++cp) 3259 free (*cp); 3260 3261 argument_count = 1; 3262 } 3263 3264 /* Flush out any data not yet sent. */ 3265 set_block (buf_to_net); 3266 buf_flush (buf_to_net, 1); 3267 3268 return; 3269 } 3270 3271 #ifdef SERVER_FLOWCONTROL 3272 /* 3273 * Called by the child at convenient points in the server's execution for 3274 * the server child to block.. ie: when it has no locks active. 3275 */ 3276 void 3277 server_pause_check() 3278 { 3279 int paused = 0; 3280 char buf[1]; 3281 3282 while (read (flowcontrol_pipe[0], buf, 1) == 1) 3283 { 3284 if (*buf == 'S') /* Stop */ 3285 paused = 1; 3286 else if (*buf == 'G') /* Go */ 3287 paused = 0; 3288 else 3289 return; /* ??? */ 3290 } 3291 while (paused) { 3292 int numfds, numtocheck; 3293 fd_set fds; 3294 3295 FD_ZERO (&fds); 3296 FD_SET (flowcontrol_pipe[0], &fds); 3297 numtocheck = flowcontrol_pipe[0] + 1; 3298 3299 do { 3300 numfds = select (numtocheck, &fds, (fd_set *)0, 3301 (fd_set *)0, (struct timeval *)NULL); 3302 if (numfds < 0 3303 && errno != EINTR) 3304 { 3305 buf_output0 (buf_to_net, "E select failed\n"); 3306 print_error (errno); 3307 return; 3308 } 3309 } while (numfds < 0); 3310 3311 if (FD_ISSET (flowcontrol_pipe[0], &fds)) 3312 { 3313 int got; 3314 3315 while ((got = read (flowcontrol_pipe[0], buf, 1)) == 1) 3316 { 3317 if (*buf == 'S') /* Stop */ 3318 paused = 1; 3319 else if (*buf == 'G') /* Go */ 3320 paused = 0; 3321 else 3322 return; /* ??? */ 3323 } 3324 3325 /* This assumes that we are using BSD or POSIX nonblocking 3326 I/O. System V nonblocking I/O returns zero if there is 3327 nothing to read. */ 3328 if (got == 0) 3329 error (1, 0, "flow control EOF"); 3330 if (got < 0 && ! blocking_error (errno)) 3331 { 3332 error (1, errno, "flow control read failed"); 3333 } 3334 } 3335 } 3336 } 3337 #endif /* SERVER_FLOWCONTROL */ 3338 3339 /* This variable commented in server.h. */ 3340 char *server_dir = NULL; 3341 3342 static void output_dir PROTO((char *, char *)); 3343 3344 static void 3345 output_dir (update_dir, repository) 3346 char *update_dir; 3347 char *repository; 3348 { 3349 if (server_dir != NULL) 3350 { 3351 buf_output0 (protocol, server_dir); 3352 buf_output0 (protocol, "/"); 3353 } 3354 if (update_dir[0] == '\0') 3355 buf_output0 (protocol, "."); 3356 else 3357 buf_output0 (protocol, update_dir); 3358 buf_output0 (protocol, "/\n"); 3359 buf_output0 (protocol, repository); 3360 buf_output0 (protocol, "/"); 3361 } 3362 3363 /* 3364 * Entries line that we are squirreling away to send to the client when 3365 * we are ready. 3366 */ 3367 static char *entries_line; 3368 3369 /* 3370 * File which has been Scratch_File'd, we are squirreling away that fact 3371 * to inform the client when we are ready. 3372 */ 3373 static char *scratched_file; 3374 3375 /* 3376 * The scratched_file will need to be removed as well as having its entry 3377 * removed. 3378 */ 3379 static int kill_scratched_file; 3380 3381 void 3382 server_register (name, version, timestamp, options, tag, date, conflict) 3383 char *name; 3384 char *version; 3385 char *timestamp; 3386 char *options; 3387 char *tag; 3388 char *date; 3389 char *conflict; 3390 { 3391 int len; 3392 3393 if (options == NULL) 3394 options = ""; 3395 3396 if (trace) 3397 { 3398 (void) fprintf (stderr, 3399 "%s-> server_register(%s, %s, %s, %s, %s, %s, %s)\n", 3400 CLIENT_SERVER_STR, 3401 name, version, timestamp ? timestamp : "", options, 3402 tag ? tag : "", date ? date : "", 3403 conflict ? conflict : ""); 3404 } 3405 3406 if (entries_line != NULL) 3407 { 3408 /* 3409 * If CVS decides to Register it more than once (which happens 3410 * on "cvs update foo/foo.c" where foo and foo.c are already 3411 * checked out), use the last of the entries lines Register'd. 3412 */ 3413 free (entries_line); 3414 } 3415 3416 /* 3417 * I have reports of Scratch_Entry and Register both happening, in 3418 * two different cases. Using the last one which happens is almost 3419 * surely correct; I haven't tracked down why they both happen (or 3420 * even verified that they are for the same file). 3421 */ 3422 if (scratched_file != NULL) 3423 { 3424 free (scratched_file); 3425 scratched_file = NULL; 3426 } 3427 3428 len = (strlen (name) + strlen (version) + strlen (options) + 80); 3429 if (tag) 3430 len += strlen (tag); 3431 if (date) 3432 len += strlen (date); 3433 3434 entries_line = xmalloc (len); 3435 sprintf (entries_line, "/%s/%s/", name, version); 3436 if (conflict != NULL) 3437 { 3438 strcat (entries_line, "+="); 3439 } 3440 strcat (entries_line, "/"); 3441 strcat (entries_line, options); 3442 strcat (entries_line, "/"); 3443 if (tag != NULL) 3444 { 3445 strcat (entries_line, "T"); 3446 strcat (entries_line, tag); 3447 } 3448 else if (date != NULL) 3449 { 3450 strcat (entries_line, "D"); 3451 strcat (entries_line, date); 3452 } 3453 } 3454 3455 void 3456 server_scratch (fname) 3457 char *fname; 3458 { 3459 /* 3460 * I have reports of Scratch_Entry and Register both happening, in 3461 * two different cases. Using the last one which happens is almost 3462 * surely correct; I haven't tracked down why they both happen (or 3463 * even verified that they are for the same file). 3464 * 3465 * Don't know if this is what whoever wrote the above comment was 3466 * talking about, but this can happen in the case where a join 3467 * removes a file - the call to Register puts the '-vers' into the 3468 * Entries file after the file is removed 3469 */ 3470 if (entries_line != NULL) 3471 { 3472 free (entries_line); 3473 entries_line = NULL; 3474 } 3475 3476 if (scratched_file != NULL) 3477 { 3478 buf_output0 (protocol, 3479 "E CVS server internal error: duplicate Scratch_Entry\n"); 3480 buf_send_counted (protocol); 3481 return; 3482 } 3483 scratched_file = xstrdup (fname); 3484 kill_scratched_file = 1; 3485 } 3486 3487 void 3488 server_scratch_entry_only () 3489 { 3490 kill_scratched_file = 0; 3491 } 3492 3493 /* Print a new entries line, from a previous server_register. */ 3494 static void 3495 new_entries_line () 3496 { 3497 if (entries_line) 3498 { 3499 buf_output0 (protocol, entries_line); 3500 buf_output (protocol, "\n", 1); 3501 } 3502 else 3503 /* Return the error message as the Entries line. */ 3504 buf_output0 (protocol, 3505 "CVS server internal error: Register missing\n"); 3506 free (entries_line); 3507 entries_line = NULL; 3508 } 3509 3510 3511 static void 3512 serve_ci (arg) 3513 char *arg; 3514 { 3515 do_cvs_command ("commit", commit); 3516 } 3517 3518 static void 3519 checked_in_response (file, update_dir, repository) 3520 char *file; 3521 char *update_dir; 3522 char *repository; 3523 { 3524 if (supported_response ("Mode")) 3525 { 3526 struct stat sb; 3527 char *mode_string; 3528 3529 if ( CVS_STAT (file, &sb) < 0) 3530 { 3531 /* Not clear to me why the file would fail to exist, but it 3532 was happening somewhere in the testsuite. */ 3533 if (!existence_error (errno)) 3534 error (0, errno, "cannot stat %s", file); 3535 } 3536 else 3537 { 3538 buf_output0 (protocol, "Mode "); 3539 mode_string = mode_to_string (sb.st_mode); 3540 buf_output0 (protocol, mode_string); 3541 buf_output0 (protocol, "\n"); 3542 free (mode_string); 3543 } 3544 } 3545 3546 buf_output0 (protocol, "Checked-in "); 3547 output_dir (update_dir, repository); 3548 buf_output0 (protocol, file); 3549 buf_output (protocol, "\n", 1); 3550 new_entries_line (); 3551 } 3552 3553 void 3554 server_checked_in (file, update_dir, repository) 3555 char *file; 3556 char *update_dir; 3557 char *repository; 3558 { 3559 if (noexec) 3560 return; 3561 if (scratched_file != NULL && entries_line == NULL) 3562 { 3563 /* 3564 * This happens if we are now doing a "cvs remove" after a previous 3565 * "cvs add" (without a "cvs ci" in between). 3566 */ 3567 buf_output0 (protocol, "Remove-entry "); 3568 output_dir (update_dir, repository); 3569 buf_output0 (protocol, file); 3570 buf_output (protocol, "\n", 1); 3571 free (scratched_file); 3572 scratched_file = NULL; 3573 } 3574 else 3575 { 3576 checked_in_response (file, update_dir, repository); 3577 } 3578 buf_send_counted (protocol); 3579 } 3580 3581 void 3582 server_update_entries (file, update_dir, repository, updated) 3583 char *file; 3584 char *update_dir; 3585 char *repository; 3586 enum server_updated_arg4 updated; 3587 { 3588 if (noexec) 3589 return; 3590 if (updated == SERVER_UPDATED) 3591 checked_in_response (file, update_dir, repository); 3592 else 3593 { 3594 if (!supported_response ("New-entry")) 3595 return; 3596 buf_output0 (protocol, "New-entry "); 3597 output_dir (update_dir, repository); 3598 buf_output0 (protocol, file); 3599 buf_output (protocol, "\n", 1); 3600 new_entries_line (); 3601 } 3602 3603 buf_send_counted (protocol); 3604 } 3605 3606 static void 3607 serve_update (arg) 3608 char *arg; 3609 { 3610 do_cvs_command ("update", update); 3611 } 3612 3613 static void 3614 serve_diff (arg) 3615 char *arg; 3616 { 3617 do_cvs_command ("diff", diff); 3618 } 3619 3620 static void 3621 serve_log (arg) 3622 char *arg; 3623 { 3624 do_cvs_command ("log", cvslog); 3625 } 3626 3627 static void 3628 serve_rlog (arg) 3629 char *arg; 3630 { 3631 /* Tell cvslog() to behave like rlog not log. */ 3632 command_name = "rlog"; 3633 do_cvs_command ("rlog", cvslog); 3634 } 3635 3636 static void 3637 serve_add (arg) 3638 char *arg; 3639 { 3640 do_cvs_command ("add", add); 3641 } 3642 3643 static void 3644 serve_remove (arg) 3645 char *arg; 3646 { 3647 do_cvs_command ("remove", cvsremove); 3648 } 3649 3650 static void 3651 serve_status (arg) 3652 char *arg; 3653 { 3654 do_cvs_command ("status", cvsstatus); 3655 } 3656 3657 static void 3658 serve_rdiff (arg) 3659 char *arg; 3660 { 3661 do_cvs_command ("rdiff", patch); 3662 } 3663 3664 static void 3665 serve_tag (arg) 3666 char *arg; 3667 { 3668 do_cvs_command ("cvstag", cvstag); 3669 } 3670 3671 static void 3672 serve_rtag (arg) 3673 char *arg; 3674 { 3675 /* Tell cvstag() to behave like rtag not tag. */ 3676 command_name = "rtag"; 3677 do_cvs_command ("rtag", cvstag); 3678 } 3679 3680 static void 3681 serve_import (arg) 3682 char *arg; 3683 { 3684 do_cvs_command ("import", import); 3685 } 3686 3687 static void 3688 serve_admin (arg) 3689 char *arg; 3690 { 3691 do_cvs_command ("admin", admin); 3692 } 3693 3694 static void 3695 serve_history (arg) 3696 char *arg; 3697 { 3698 do_cvs_command ("history", history); 3699 } 3700 3701 static void 3702 serve_release (arg) 3703 char *arg; 3704 { 3705 do_cvs_command ("release", release); 3706 } 3707 3708 static void serve_watch_on PROTO ((char *)); 3709 3710 static void 3711 serve_watch_on (arg) 3712 char *arg; 3713 { 3714 do_cvs_command ("watch_on", watch_on); 3715 } 3716 3717 static void serve_watch_off PROTO ((char *)); 3718 3719 static void 3720 serve_watch_off (arg) 3721 char *arg; 3722 { 3723 do_cvs_command ("watch_off", watch_off); 3724 } 3725 3726 static void serve_watch_add PROTO ((char *)); 3727 3728 static void 3729 serve_watch_add (arg) 3730 char *arg; 3731 { 3732 do_cvs_command ("watch_add", watch_add); 3733 } 3734 3735 static void serve_watch_remove PROTO ((char *)); 3736 3737 static void 3738 serve_watch_remove (arg) 3739 char *arg; 3740 { 3741 do_cvs_command ("watch_remove", watch_remove); 3742 } 3743 3744 static void serve_watchers PROTO ((char *)); 3745 3746 static void 3747 serve_watchers (arg) 3748 char *arg; 3749 { 3750 do_cvs_command ("watchers", watchers); 3751 } 3752 3753 static void serve_editors PROTO ((char *)); 3754 3755 static void 3756 serve_editors (arg) 3757 char *arg; 3758 { 3759 do_cvs_command ("editors", editors); 3760 } 3761 3762 static void serve_noop PROTO ((char *)); 3763 3764 static void 3765 serve_noop (arg) 3766 char *arg; 3767 { 3768 3769 server_write_entries (); 3770 if (!print_pending_error ()) 3771 { 3772 (void) server_notify (); 3773 buf_output0 (buf_to_net, "ok\n"); 3774 } 3775 buf_flush (buf_to_net, 1); 3776 } 3777 3778 static void serve_version PROTO ((char *)); 3779 3780 static void 3781 serve_version (arg) 3782 char *arg; 3783 { 3784 do_cvs_command ("version", version); 3785 } 3786 3787 static void serve_init PROTO ((char *)); 3788 3789 static void 3790 serve_init (arg) 3791 char *arg; 3792 { 3793 if (!isabsolute (arg)) 3794 { 3795 if (alloc_pending (80 + strlen (arg))) 3796 sprintf (pending_error_text, 3797 "E Root %s must be an absolute pathname", arg); 3798 /* Fall through to do_cvs_command which will return the 3799 actual error. */ 3800 } 3801 3802 if (current_parsed_root != NULL) 3803 free_cvsroot_t (current_parsed_root); 3804 current_parsed_root = local_cvsroot (arg); 3805 3806 do_cvs_command ("init", init); 3807 } 3808 3809 static void serve_annotate PROTO ((char *)); 3810 3811 static void 3812 serve_annotate (arg) 3813 char *arg; 3814 { 3815 do_cvs_command ("annotate", annotate); 3816 } 3817 3818 static void serve_rannotate PROTO ((char *)); 3819 3820 static void 3821 serve_rannotate (arg) 3822 char *arg; 3823 { 3824 /* Tell annotate() to behave like rannotate not annotate. */ 3825 command_name = "rannotate"; 3826 do_cvs_command ("rannotate", annotate); 3827 } 3828 3829 static void 3830 serve_co (arg) 3831 char *arg; 3832 { 3833 char *tempdir; 3834 int status; 3835 3836 if (print_pending_error ()) 3837 return; 3838 3839 if (!isdir (CVSADM)) 3840 { 3841 /* 3842 * The client has not sent a "Repository" line. Check out 3843 * into a pristine directory. 3844 */ 3845 tempdir = malloc (strlen (server_temp_dir) + 80); 3846 if (tempdir == NULL) 3847 { 3848 buf_output0 (buf_to_net, "E Out of memory\n"); 3849 return; 3850 } 3851 strcpy (tempdir, server_temp_dir); 3852 strcat (tempdir, "/checkout-dir"); 3853 status = mkdir_p (tempdir); 3854 if (status != 0 && status != EEXIST) 3855 { 3856 buf_output0 (buf_to_net, "E Cannot create "); 3857 buf_output0 (buf_to_net, tempdir); 3858 buf_append_char (buf_to_net, '\n'); 3859 print_error (errno); 3860 free (tempdir); 3861 return; 3862 } 3863 3864 if ( CVS_CHDIR (tempdir) < 0) 3865 { 3866 buf_output0 (buf_to_net, "E Cannot change to directory "); 3867 buf_output0 (buf_to_net, tempdir); 3868 buf_append_char (buf_to_net, '\n'); 3869 print_error (errno); 3870 free (tempdir); 3871 return; 3872 } 3873 free (tempdir); 3874 } 3875 3876 /* Compensate for server_export()'s setting of command_name. 3877 * 3878 * [It probably doesn't matter if do_cvs_command() gets "export" 3879 * or "checkout", but we ought to be accurate where possible.] 3880 */ 3881 do_cvs_command ((strcmp (command_name, "export") == 0) ? 3882 "export" : "checkout", 3883 checkout); 3884 } 3885 3886 static void 3887 serve_export (arg) 3888 char *arg; 3889 { 3890 /* Tell checkout() to behave like export not checkout. */ 3891 command_name = "export"; 3892 serve_co (arg); 3893 } 3894 3895 void 3896 server_copy_file (file, update_dir, repository, newfile) 3897 char *file; 3898 char *update_dir; 3899 char *repository; 3900 char *newfile; 3901 { 3902 /* At least for now, our practice is to have the server enforce 3903 noexec for the repository and the client enforce it for the 3904 working directory. This might want more thought, and/or 3905 documentation in cvsclient.texi (other responses do it 3906 differently). */ 3907 3908 if (!supported_response ("Copy-file")) 3909 return; 3910 buf_output0 (protocol, "Copy-file "); 3911 output_dir (update_dir, repository); 3912 buf_output0 (protocol, file); 3913 buf_output0 (protocol, "\n"); 3914 buf_output0 (protocol, newfile); 3915 buf_output0 (protocol, "\n"); 3916 } 3917 3918 /* See server.h for description. */ 3919 3920 void 3921 server_modtime (finfo, vers_ts) 3922 struct file_info *finfo; 3923 Vers_TS *vers_ts; 3924 { 3925 char date[MAXDATELEN]; 3926 char outdate[MAXDATELEN]; 3927 3928 assert (vers_ts->vn_rcs != NULL); 3929 3930 if (!supported_response ("Mod-time")) 3931 return; 3932 3933 if (RCS_getrevtime (finfo->rcs, vers_ts->vn_rcs, date, 0) == (time_t) -1) 3934 /* FIXME? should we be printing some kind of warning? For one 3935 thing I'm not 100% sure whether this happens in non-error 3936 circumstances. */ 3937 return; 3938 date_to_internet (outdate, date); 3939 buf_output0 (protocol, "Mod-time "); 3940 buf_output0 (protocol, outdate); 3941 buf_output0 (protocol, "\n"); 3942 } 3943 3944 /* See server.h for description. */ 3945 3946 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) 3947 /* Need to prototype because mode_t might be smaller than int. */ 3948 void 3949 server_updated ( 3950 struct file_info *finfo, 3951 Vers_TS *vers, 3952 enum server_updated_arg4 updated, 3953 mode_t mode, 3954 unsigned char *checksum, 3955 struct buffer *filebuf) 3956 #else 3957 void 3958 server_updated (finfo, vers, updated, mode, checksum, filebuf) 3959 struct file_info *finfo; 3960 Vers_TS *vers; 3961 enum server_updated_arg4 updated; 3962 mode_t mode; 3963 unsigned char *checksum; 3964 struct buffer *filebuf; 3965 #endif 3966 { 3967 if (noexec) 3968 { 3969 /* Hmm, maybe if we did the same thing for entries_file, we 3970 could get rid of the kludges in server_register and 3971 server_scratch which refrain from warning if both 3972 Scratch_Entry and Register get called. Maybe. */ 3973 if (scratched_file) 3974 { 3975 free (scratched_file); 3976 scratched_file = NULL; 3977 } 3978 return; 3979 } 3980 3981 if (entries_line != NULL && scratched_file == NULL) 3982 { 3983 FILE *f; 3984 struct buffer_data *list, *last; 3985 unsigned long size; 3986 char size_text[80]; 3987 3988 /* The contents of the file will be in one of filebuf, 3989 list/last, or here. */ 3990 unsigned char *file; 3991 size_t file_allocated; 3992 size_t file_used; 3993 3994 if (filebuf != NULL) 3995 { 3996 size = buf_length (filebuf); 3997 if (mode == (mode_t) -1) 3998 error (1, 0, "\ 3999 CVS server internal error: no mode in server_updated"); 4000 } 4001 else 4002 { 4003 struct stat sb; 4004 4005 if ( CVS_STAT (finfo->file, &sb) < 0) 4006 { 4007 if (existence_error (errno)) 4008 { 4009 /* If we have a sticky tag for a branch on which 4010 the file is dead, and cvs update the directory, 4011 it gets a T_CHECKOUT but no file. So in this 4012 case just forget the whole thing. */ 4013 free (entries_line); 4014 entries_line = NULL; 4015 goto done; 4016 } 4017 error (1, errno, "reading %s", finfo->fullname); 4018 } 4019 size = sb.st_size; 4020 if (mode == (mode_t) -1) 4021 { 4022 /* FIXME: When we check out files the umask of the 4023 server (set in .bashrc if rsh is in use) affects 4024 what mode we send, and it shouldn't. */ 4025 mode = sb.st_mode; 4026 } 4027 } 4028 4029 if (checksum != NULL) 4030 { 4031 static int checksum_supported = -1; 4032 4033 if (checksum_supported == -1) 4034 { 4035 checksum_supported = supported_response ("Checksum"); 4036 } 4037 4038 if (checksum_supported) 4039 { 4040 int i; 4041 char buf[3]; 4042 4043 buf_output0 (protocol, "Checksum "); 4044 for (i = 0; i < 16; i++) 4045 { 4046 sprintf (buf, "%02x", (unsigned int) checksum[i]); 4047 buf_output0 (protocol, buf); 4048 } 4049 buf_append_char (protocol, '\n'); 4050 } 4051 } 4052 4053 if (updated == SERVER_UPDATED) 4054 { 4055 Node *node; 4056 Entnode *entnode; 4057 4058 if (!(supported_response ("Created") 4059 && supported_response ("Update-existing"))) 4060 buf_output0 (protocol, "Updated "); 4061 else 4062 { 4063 assert (vers != NULL); 4064 if (vers->ts_user == NULL) 4065 buf_output0 (protocol, "Created "); 4066 else 4067 buf_output0 (protocol, "Update-existing "); 4068 } 4069 4070 /* Now munge the entries to say that the file is unmodified, 4071 in case we end up processing it again (e.g. modules3-6 4072 in the testsuite). */ 4073 node = findnode_fn (finfo->entries, finfo->file); 4074 entnode = (Entnode *)node->data; 4075 free (entnode->timestamp); 4076 entnode->timestamp = xstrdup ("="); 4077 } 4078 else if (updated == SERVER_MERGED) 4079 buf_output0 (protocol, "Merged "); 4080 else if (updated == SERVER_PATCHED) 4081 buf_output0 (protocol, "Patched "); 4082 else if (updated == SERVER_RCS_DIFF) 4083 buf_output0 (protocol, "Rcs-diff "); 4084 else 4085 abort (); 4086 output_dir (finfo->update_dir, finfo->repository); 4087 buf_output0 (protocol, finfo->file); 4088 buf_output (protocol, "\n", 1); 4089 4090 new_entries_line (); 4091 4092 { 4093 char *mode_string; 4094 4095 mode_string = mode_to_string (mode); 4096 buf_output0 (protocol, mode_string); 4097 buf_output0 (protocol, "\n"); 4098 free (mode_string); 4099 } 4100 4101 list = last = NULL; 4102 4103 file = NULL; 4104 file_allocated = 0; 4105 file_used = 0; 4106 4107 if (size > 0) 4108 { 4109 /* Throughout this section we use binary mode to read the 4110 file we are sending. The client handles any line ending 4111 translation if necessary. */ 4112 4113 if (file_gzip_level 4114 /* 4115 * For really tiny files, the gzip process startup 4116 * time will outweigh the compression savings. This 4117 * might be computable somehow; using 100 here is just 4118 * a first approximation. 4119 */ 4120 && size > 100) 4121 { 4122 /* Basing this routine on read_and_gzip is not a 4123 high-performance approach. But it seems easier 4124 to code than the alternative (and less 4125 vulnerable to subtle bugs). Given that this feature 4126 is mainly for compatibility, that is the better 4127 tradeoff. */ 4128 4129 int fd; 4130 4131 /* Callers must avoid passing us a buffer if 4132 file_gzip_level is set. We could handle this case, 4133 but it's not worth it since this case never arises 4134 with a current client and server. */ 4135 if (filebuf != NULL) 4136 error (1, 0, "\ 4137 CVS server internal error: unhandled case in server_updated"); 4138 4139 fd = CVS_OPEN (finfo->file, O_RDONLY | OPEN_BINARY, 0); 4140 if (fd < 0) 4141 error (1, errno, "reading %s", finfo->fullname); 4142 if (read_and_gzip (fd, finfo->fullname, &file, 4143 &file_allocated, &file_used, 4144 file_gzip_level)) 4145 error (1, 0, "aborting due to compression error"); 4146 size = file_used; 4147 if (close (fd) < 0) 4148 error (1, errno, "reading %s", finfo->fullname); 4149 /* Prepending length with "z" is flag for using gzip here. */ 4150 buf_output0 (protocol, "z"); 4151 } 4152 else if (filebuf == NULL) 4153 { 4154 long status; 4155 4156 f = CVS_FOPEN (finfo->file, "rb"); 4157 if (f == NULL) 4158 error (1, errno, "reading %s", finfo->fullname); 4159 status = buf_read_file (f, size, &list, &last); 4160 if (status == -2) 4161 (*protocol->memory_error) (protocol); 4162 else if (status != 0) 4163 error (1, ferror (f) ? errno : 0, "reading %s", 4164 finfo->fullname); 4165 if (fclose (f) == EOF) 4166 error (1, errno, "reading %s", finfo->fullname); 4167 } 4168 } 4169 4170 sprintf (size_text, "%lu\n", size); 4171 buf_output0 (protocol, size_text); 4172 4173 if (file != NULL) 4174 { 4175 buf_output (protocol, (char *) file, file_used); 4176 free (file); 4177 file = NULL; 4178 } 4179 else if (filebuf == NULL) 4180 buf_append_data (protocol, list, last); 4181 else 4182 { 4183 buf_append_buffer (protocol, filebuf); 4184 buf_free (filebuf); 4185 } 4186 /* Note we only send a newline here if the file ended with one. */ 4187 4188 /* 4189 * Avoid using up too much disk space for temporary files. 4190 * A file which does not exist indicates that the file is up-to-date, 4191 * which is now the case. If this is SERVER_MERGED, the file is 4192 * not up-to-date, and we indicate that by leaving the file there. 4193 * I'm thinking of cases like "cvs update foo/foo.c foo". 4194 */ 4195 if ((updated == SERVER_UPDATED 4196 || updated == SERVER_PATCHED 4197 || updated == SERVER_RCS_DIFF) 4198 && filebuf == NULL 4199 /* But if we are joining, we'll need the file when we call 4200 join_file. */ 4201 && !joining ()) 4202 { 4203 if (CVS_UNLINK (finfo->file) < 0) 4204 error (0, errno, "cannot remove temp file for %s", 4205 finfo->fullname); 4206 } 4207 } 4208 else if (scratched_file != NULL && entries_line == NULL) 4209 { 4210 if (strcmp (scratched_file, finfo->file) != 0) 4211 error (1, 0, 4212 "CVS server internal error: `%s' vs. `%s' scratched", 4213 scratched_file, 4214 finfo->file); 4215 free (scratched_file); 4216 scratched_file = NULL; 4217 4218 if (kill_scratched_file) 4219 buf_output0 (protocol, "Removed "); 4220 else 4221 buf_output0 (protocol, "Remove-entry "); 4222 output_dir (finfo->update_dir, finfo->repository); 4223 buf_output0 (protocol, finfo->file); 4224 buf_output (protocol, "\n", 1); 4225 /* keep the vers structure up to date in case we do a join 4226 * - if there isn't a file, it can't very well have a version number, can it? 4227 * 4228 * we do it here on the assumption that since we just told the client 4229 * to remove the file/entry, it will, and we want to remember that. 4230 * If it fails, that's the client's problem, not ours 4231 */ 4232 if (vers && vers->vn_user != NULL) 4233 { 4234 free (vers->vn_user); 4235 vers->vn_user = NULL; 4236 } 4237 if (vers && vers->ts_user != NULL) 4238 { 4239 free (vers->ts_user); 4240 vers->ts_user = NULL; 4241 } 4242 } 4243 else if (scratched_file == NULL && entries_line == NULL) 4244 { 4245 /* 4246 * This can happen with death support if we were processing 4247 * a dead file in a checkout. 4248 */ 4249 } 4250 else 4251 error (1, 0, 4252 "CVS server internal error: Register *and* Scratch_Entry.\n"); 4253 buf_send_counted (protocol); 4254 done:; 4255 } 4256 4257 /* Return whether we should send patches in RCS format. */ 4258 4259 int 4260 server_use_rcs_diff () 4261 { 4262 return supported_response ("Rcs-diff"); 4263 } 4264 4265 void 4266 server_set_entstat (update_dir, repository) 4267 char *update_dir; 4268 char *repository; 4269 { 4270 static int set_static_supported = -1; 4271 if (set_static_supported == -1) 4272 set_static_supported = supported_response ("Set-static-directory"); 4273 if (!set_static_supported) return; 4274 4275 buf_output0 (protocol, "Set-static-directory "); 4276 output_dir (update_dir, repository); 4277 buf_output0 (protocol, "\n"); 4278 buf_send_counted (protocol); 4279 } 4280 4281 void 4282 server_clear_entstat (update_dir, repository) 4283 char *update_dir; 4284 char *repository; 4285 { 4286 static int clear_static_supported = -1; 4287 if (clear_static_supported == -1) 4288 clear_static_supported = supported_response ("Clear-static-directory"); 4289 if (!clear_static_supported) return; 4290 4291 if (noexec) 4292 return; 4293 4294 buf_output0 (protocol, "Clear-static-directory "); 4295 output_dir (update_dir, repository); 4296 buf_output0 (protocol, "\n"); 4297 buf_send_counted (protocol); 4298 } 4299 4300 void 4301 server_set_sticky (update_dir, repository, tag, date, nonbranch) 4302 char *update_dir; 4303 char *repository; 4304 char *tag; 4305 char *date; 4306 int nonbranch; 4307 { 4308 static int set_sticky_supported = -1; 4309 4310 assert (update_dir != NULL); 4311 4312 if (set_sticky_supported == -1) 4313 set_sticky_supported = supported_response ("Set-sticky"); 4314 if (!set_sticky_supported) return; 4315 4316 if (noexec) 4317 return; 4318 4319 if (tag == NULL && date == NULL) 4320 { 4321 buf_output0 (protocol, "Clear-sticky "); 4322 output_dir (update_dir, repository); 4323 buf_output0 (protocol, "\n"); 4324 } 4325 else 4326 { 4327 buf_output0 (protocol, "Set-sticky "); 4328 output_dir (update_dir, repository); 4329 buf_output0 (protocol, "\n"); 4330 if (tag != NULL) 4331 { 4332 if (nonbranch) 4333 buf_output0 (protocol, "N"); 4334 else 4335 buf_output0 (protocol, "T"); 4336 buf_output0 (protocol, tag); 4337 } 4338 else 4339 { 4340 buf_output0 (protocol, "D"); 4341 buf_output0 (protocol, date); 4342 } 4343 buf_output0 (protocol, "\n"); 4344 } 4345 buf_send_counted (protocol); 4346 } 4347 4348 struct template_proc_data 4349 { 4350 char *update_dir; 4351 char *repository; 4352 }; 4353 4354 /* Here as a static until we get around to fixing Parse_Info to pass along 4355 a void * for it. */ 4356 static struct template_proc_data *tpd; 4357 4358 static int 4359 template_proc (repository, template) 4360 char *repository; 4361 char *template; 4362 { 4363 FILE *fp; 4364 char buf[1024]; 4365 size_t n; 4366 struct stat sb; 4367 struct template_proc_data *data = tpd; 4368 4369 if (!supported_response ("Template")) 4370 /* Might want to warn the user that the rcsinfo feature won't work. */ 4371 return 0; 4372 buf_output0 (protocol, "Template "); 4373 output_dir (data->update_dir, data->repository); 4374 buf_output0 (protocol, "\n"); 4375 4376 fp = CVS_FOPEN (template, "rb"); 4377 if (fp == NULL) 4378 { 4379 error (0, errno, "Couldn't open rcsinfo template file %s", template); 4380 return 1; 4381 } 4382 if (fstat (fileno (fp), &sb) < 0) 4383 { 4384 error (0, errno, "cannot stat rcsinfo template file %s", template); 4385 return 1; 4386 } 4387 sprintf (buf, "%ld\n", (long) sb.st_size); 4388 buf_output0 (protocol, buf); 4389 while (!feof (fp)) 4390 { 4391 n = fread (buf, 1, sizeof buf, fp); 4392 buf_output (protocol, buf, n); 4393 if (ferror (fp)) 4394 { 4395 error (0, errno, "cannot read rcsinfo template file %s", template); 4396 (void) fclose (fp); 4397 return 1; 4398 } 4399 } 4400 if (fclose (fp) < 0) 4401 error (0, errno, "cannot close rcsinfo template file %s", template); 4402 return 0; 4403 } 4404 4405 void 4406 server_template (update_dir, repository) 4407 char *update_dir; 4408 char *repository; 4409 { 4410 struct template_proc_data data; 4411 data.update_dir = update_dir; 4412 data.repository = repository; 4413 tpd = &data; 4414 (void) Parse_Info (CVSROOTADM_RCSINFO, repository, template_proc, 1); 4415 } 4416 4417 static void 4418 serve_gzip_contents (arg) 4419 char *arg; 4420 { 4421 int level; 4422 level = atoi (arg); 4423 if (level == 0) 4424 level = 6; 4425 file_gzip_level = level; 4426 } 4427 4428 static void 4429 serve_gzip_stream (arg) 4430 char *arg; 4431 { 4432 int level; 4433 level = atoi (arg); 4434 if (level == 0) 4435 level = 6; 4436 4437 /* All further communication with the client will be compressed. */ 4438 4439 buf_to_net = compress_buffer_initialize (buf_to_net, 0, level, 4440 buf_to_net->memory_error); 4441 buf_from_net = compress_buffer_initialize (buf_from_net, 1, level, 4442 buf_from_net->memory_error); 4443 } 4444 4445 /* Tell the client about RCS options set in CVSROOT/cvswrappers. */ 4446 static void 4447 serve_wrapper_sendme_rcs_options (arg) 4448 char *arg; 4449 { 4450 /* Actually, this is kind of sdrawkcab-ssa: the client wants 4451 * verbatim lines from a cvswrappers file, but the server has 4452 * already parsed the cvswrappers file into the wrap_list struct. 4453 * Therefore, the server loops over wrap_list, unparsing each 4454 * entry before sending it. 4455 */ 4456 char *wrapper_line = NULL; 4457 4458 wrap_setup (); 4459 4460 for (wrap_unparse_rcs_options (&wrapper_line, 1); 4461 wrapper_line; 4462 wrap_unparse_rcs_options (&wrapper_line, 0)) 4463 { 4464 buf_output0 (buf_to_net, "Wrapper-rcsOption "); 4465 buf_output0 (buf_to_net, wrapper_line); 4466 buf_output0 (buf_to_net, "\012");; 4467 free (wrapper_line); 4468 } 4469 4470 buf_output0 (buf_to_net, "ok\012"); 4471 4472 /* The client is waiting for us, so we better send the data now. */ 4473 buf_flush (buf_to_net, 1); 4474 } 4475 4476 4477 static void 4478 serve_ignore (arg) 4479 char *arg; 4480 { 4481 /* 4482 * Just ignore this command. This is used to support the 4483 * update-patches command, which is not a real command, but a signal 4484 * to the client that update will accept the -u argument. 4485 */ 4486 } 4487 4488 static int 4489 expand_proc (argc, argv, where, mwhere, mfile, shorten, 4490 local_specified, omodule, msg) 4491 int argc; 4492 char **argv; 4493 char *where; 4494 char *mwhere; 4495 char *mfile; 4496 int shorten; 4497 int local_specified; 4498 char *omodule; 4499 char *msg; 4500 { 4501 int i; 4502 char *dir = argv[0]; 4503 4504 /* If mwhere has been specified, the thing we're expanding is a 4505 module -- just return its name so the client will ask for the 4506 right thing later. If it is an alias or a real directory, 4507 mwhere will not be set, so send out the appropriate 4508 expansion. */ 4509 4510 if (mwhere != NULL) 4511 { 4512 buf_output0 (buf_to_net, "Module-expansion "); 4513 if (server_dir != NULL) 4514 { 4515 buf_output0 (buf_to_net, server_dir); 4516 buf_output0 (buf_to_net, "/"); 4517 } 4518 buf_output0 (buf_to_net, mwhere); 4519 if (mfile != NULL) 4520 { 4521 buf_append_char (buf_to_net, '/'); 4522 buf_output0 (buf_to_net, mfile); 4523 } 4524 buf_append_char (buf_to_net, '\n'); 4525 } 4526 else 4527 { 4528 /* We may not need to do this anymore -- check the definition 4529 of aliases before removing */ 4530 if (argc == 1) 4531 { 4532 buf_output0 (buf_to_net, "Module-expansion "); 4533 if (server_dir != NULL) 4534 { 4535 buf_output0 (buf_to_net, server_dir); 4536 buf_output0 (buf_to_net, "/"); 4537 } 4538 buf_output0 (buf_to_net, dir); 4539 buf_append_char (buf_to_net, '\n'); 4540 } 4541 else 4542 { 4543 for (i = 1; i < argc; ++i) 4544 { 4545 buf_output0 (buf_to_net, "Module-expansion "); 4546 if (server_dir != NULL) 4547 { 4548 buf_output0 (buf_to_net, server_dir); 4549 buf_output0 (buf_to_net, "/"); 4550 } 4551 buf_output0 (buf_to_net, dir); 4552 buf_append_char (buf_to_net, '/'); 4553 buf_output0 (buf_to_net, argv[i]); 4554 buf_append_char (buf_to_net, '\n'); 4555 } 4556 } 4557 } 4558 return 0; 4559 } 4560 4561 static void 4562 serve_expand_modules (arg) 4563 char *arg; 4564 { 4565 int i; 4566 int err; 4567 DBM *db; 4568 err = 0; 4569 4570 server_expanding = 1; 4571 db = open_module (); 4572 for (i = 1; i < argument_count; i++) 4573 err += do_module (db, argument_vector[i], 4574 CHECKOUT, "Updating", expand_proc, 4575 NULL, 0, 0, 0, 0, 4576 (char *) NULL); 4577 close_module (db); 4578 server_expanding = 0; 4579 { 4580 /* argument_vector[0] is a dummy argument, we don't mess with it. */ 4581 char **cp; 4582 for (cp = argument_vector + 1; 4583 cp < argument_vector + argument_count; 4584 ++cp) 4585 free (*cp); 4586 4587 argument_count = 1; 4588 } 4589 if (err) 4590 /* We will have printed an error message already. */ 4591 buf_output0 (buf_to_net, "error \n"); 4592 else 4593 buf_output0 (buf_to_net, "ok\n"); 4594 4595 /* The client is waiting for the module expansions, so we must 4596 send the output now. */ 4597 buf_flush (buf_to_net, 1); 4598 } 4599 4600 void 4601 server_prog (dir, name, which) 4602 char *dir; 4603 char *name; 4604 enum progs which; 4605 { 4606 if (!supported_response ("Set-checkin-prog")) 4607 { 4608 buf_output0 (buf_to_net, "E \ 4609 warning: this client does not support -i or -u flags in the modules file.\n"); 4610 return; 4611 } 4612 switch (which) 4613 { 4614 case PROG_CHECKIN: 4615 buf_output0 (buf_to_net, "Set-checkin-prog "); 4616 break; 4617 case PROG_UPDATE: 4618 buf_output0 (buf_to_net, "Set-update-prog "); 4619 break; 4620 } 4621 buf_output0 (buf_to_net, dir); 4622 buf_append_char (buf_to_net, '\n'); 4623 buf_output0 (buf_to_net, name); 4624 buf_append_char (buf_to_net, '\n'); 4625 } 4626 4627 static void 4628 serve_checkin_prog (arg) 4629 char *arg; 4630 { 4631 FILE *f; 4632 f = CVS_FOPEN (CVSADM_CIPROG, "w+"); 4633 if (f == NULL) 4634 { 4635 int save_errno = errno; 4636 if (alloc_pending (80 + strlen (CVSADM_CIPROG))) 4637 sprintf (pending_error_text, "E cannot open %s", CVSADM_CIPROG); 4638 pending_error = save_errno; 4639 return; 4640 } 4641 if (fprintf (f, "%s\n", arg) < 0) 4642 { 4643 int save_errno = errno; 4644 if (alloc_pending (80 + strlen (CVSADM_CIPROG))) 4645 sprintf (pending_error_text, 4646 "E cannot write to %s", CVSADM_CIPROG); 4647 pending_error = save_errno; 4648 return; 4649 } 4650 if (fclose (f) == EOF) 4651 { 4652 int save_errno = errno; 4653 if (alloc_pending (80 + strlen (CVSADM_CIPROG))) 4654 sprintf (pending_error_text, "E cannot close %s", CVSADM_CIPROG); 4655 pending_error = save_errno; 4656 return; 4657 } 4658 } 4659 4660 static void 4661 serve_update_prog (arg) 4662 char *arg; 4663 { 4664 FILE *f; 4665 4666 /* Before we do anything we need to make sure we are not in readonly 4667 mode. */ 4668 if (!check_command_legal_p ("commit")) 4669 { 4670 /* I might be willing to make this a warning, except we lack the 4671 machinery to do so. */ 4672 if (alloc_pending (80)) 4673 sprintf (pending_error_text, "\ 4674 E Flag -u in modules not allowed in readonly mode"); 4675 return; 4676 } 4677 4678 f = CVS_FOPEN (CVSADM_UPROG, "w+"); 4679 if (f == NULL) 4680 { 4681 int save_errno = errno; 4682 if (alloc_pending (80 + strlen (CVSADM_UPROG))) 4683 sprintf (pending_error_text, "E cannot open %s", CVSADM_UPROG); 4684 pending_error = save_errno; 4685 return; 4686 } 4687 if (fprintf (f, "%s\n", arg) < 0) 4688 { 4689 int save_errno = errno; 4690 if (alloc_pending (80 + strlen (CVSADM_UPROG))) 4691 sprintf (pending_error_text, "E cannot write to %s", CVSADM_UPROG); 4692 pending_error = save_errno; 4693 return; 4694 } 4695 if (fclose (f) == EOF) 4696 { 4697 int save_errno = errno; 4698 if (alloc_pending (80 + strlen (CVSADM_UPROG))) 4699 sprintf (pending_error_text, "E cannot close %s", CVSADM_UPROG); 4700 pending_error = save_errno; 4701 return; 4702 } 4703 } 4704 4705 static void serve_valid_requests PROTO((char *arg)); 4706 4707 #endif /* SERVER_SUPPORT */ 4708 #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) 4709 4710 /* 4711 * Parts of this table are shared with the client code, 4712 * but the client doesn't need to know about the handler 4713 * functions. 4714 */ 4715 4716 struct request requests[] = 4717 { 4718 #ifdef SERVER_SUPPORT 4719 #define REQ_LINE(n, f, s) {n, f, s} 4720 #else 4721 #define REQ_LINE(n, f, s) {n, s} 4722 #endif 4723 4724 REQ_LINE("Root", serve_root, RQ_ESSENTIAL | RQ_ROOTLESS), 4725 REQ_LINE("Valid-responses", serve_valid_responses, 4726 RQ_ESSENTIAL | RQ_ROOTLESS), 4727 REQ_LINE("valid-requests", serve_valid_requests, 4728 RQ_ESSENTIAL | RQ_ROOTLESS), 4729 REQ_LINE("Repository", serve_repository, 0), 4730 REQ_LINE("Directory", serve_directory, RQ_ESSENTIAL), 4731 REQ_LINE("Max-dotdot", serve_max_dotdot, 0), 4732 REQ_LINE("Static-directory", serve_static_directory, 0), 4733 REQ_LINE("Sticky", serve_sticky, 0), 4734 REQ_LINE("Checkin-prog", serve_checkin_prog, 0), 4735 REQ_LINE("Update-prog", serve_update_prog, 0), 4736 REQ_LINE("Entry", serve_entry, RQ_ESSENTIAL), 4737 REQ_LINE("Kopt", serve_kopt, 0), 4738 REQ_LINE("Checkin-time", serve_checkin_time, 0), 4739 REQ_LINE("Modified", serve_modified, RQ_ESSENTIAL), 4740 REQ_LINE("Is-modified", serve_is_modified, 0), 4741 4742 /* The client must send this request to interoperate with CVS 1.5 4743 through 1.9 servers. The server must support it (although it can 4744 be and is a noop) to interoperate with CVS 1.5 to 1.9 clients. */ 4745 REQ_LINE("UseUnchanged", serve_enable_unchanged, RQ_ENABLEME | RQ_ROOTLESS), 4746 4747 REQ_LINE("Unchanged", serve_unchanged, RQ_ESSENTIAL), 4748 REQ_LINE("Notify", serve_notify, 0), 4749 REQ_LINE("Questionable", serve_questionable, 0), 4750 REQ_LINE("Case", serve_case, 0), 4751 REQ_LINE("Argument", serve_argument, RQ_ESSENTIAL), 4752 REQ_LINE("Argumentx", serve_argumentx, RQ_ESSENTIAL), 4753 REQ_LINE("Global_option", serve_global_option, RQ_ROOTLESS), 4754 REQ_LINE("Gzip-stream", serve_gzip_stream, 0), 4755 REQ_LINE("wrapper-sendme-rcsOptions", 4756 serve_wrapper_sendme_rcs_options, 4757 0), 4758 REQ_LINE("Set", serve_set, RQ_ROOTLESS), 4759 #ifdef ENCRYPTION 4760 # ifdef HAVE_KERBEROS 4761 REQ_LINE("Kerberos-encrypt", serve_kerberos_encrypt, 0), 4762 # endif 4763 # ifdef HAVE_GSSAPI 4764 REQ_LINE("Gssapi-encrypt", serve_gssapi_encrypt, 0), 4765 # endif 4766 #endif 4767 #ifdef HAVE_GSSAPI 4768 REQ_LINE("Gssapi-authenticate", serve_gssapi_authenticate, 0), 4769 #endif 4770 REQ_LINE("expand-modules", serve_expand_modules, 0), 4771 REQ_LINE("ci", serve_ci, RQ_ESSENTIAL), 4772 REQ_LINE("co", serve_co, RQ_ESSENTIAL), 4773 REQ_LINE("update", serve_update, RQ_ESSENTIAL), 4774 REQ_LINE("diff", serve_diff, 0), 4775 REQ_LINE("log", serve_log, 0), 4776 REQ_LINE("rlog", serve_rlog, 0), 4777 REQ_LINE("add", serve_add, 0), 4778 REQ_LINE("remove", serve_remove, 0), 4779 REQ_LINE("update-patches", serve_ignore, 0), 4780 REQ_LINE("gzip-file-contents", serve_gzip_contents, 0), 4781 REQ_LINE("status", serve_status, 0), 4782 REQ_LINE("rdiff", serve_rdiff, 0), 4783 REQ_LINE("tag", serve_tag, 0), 4784 REQ_LINE("rtag", serve_rtag, 0), 4785 REQ_LINE("import", serve_import, 0), 4786 REQ_LINE("admin", serve_admin, 0), 4787 REQ_LINE("export", serve_export, 0), 4788 REQ_LINE("history", serve_history, 0), 4789 REQ_LINE("release", serve_release, 0), 4790 REQ_LINE("watch-on", serve_watch_on, 0), 4791 REQ_LINE("watch-off", serve_watch_off, 0), 4792 REQ_LINE("watch-add", serve_watch_add, 0), 4793 REQ_LINE("watch-remove", serve_watch_remove, 0), 4794 REQ_LINE("watchers", serve_watchers, 0), 4795 REQ_LINE("editors", serve_editors, 0), 4796 REQ_LINE("init", serve_init, RQ_ROOTLESS), 4797 REQ_LINE("annotate", serve_annotate, 0), 4798 REQ_LINE("rannotate", serve_rannotate, 0), 4799 REQ_LINE("noop", serve_noop, RQ_ROOTLESS), 4800 REQ_LINE("version", serve_version, RQ_ROOTLESS), 4801 REQ_LINE(NULL, NULL, 0) 4802 4803 #undef REQ_LINE 4804 }; 4805 4806 #endif /* SERVER_SUPPORT or CLIENT_SUPPORT */ 4807 #ifdef SERVER_SUPPORT 4808 4809 static void 4810 serve_valid_requests (arg) 4811 char *arg; 4812 { 4813 struct request *rq; 4814 if (print_pending_error ()) 4815 return; 4816 buf_output0 (buf_to_net, "Valid-requests"); 4817 for (rq = requests; rq->name != NULL; rq++) 4818 { 4819 if (rq->func != NULL) 4820 { 4821 buf_append_char (buf_to_net, ' '); 4822 buf_output0 (buf_to_net, rq->name); 4823 } 4824 } 4825 buf_output0 (buf_to_net, "\nok\n"); 4826 4827 /* The client is waiting for the list of valid requests, so we 4828 must send the output now. */ 4829 buf_flush (buf_to_net, 1); 4830 } 4831 4832 #ifdef SUNOS_KLUDGE 4833 /* 4834 * Delete temporary files. SIG is the signal making this happen, or 4835 * 0 if not called as a result of a signal. 4836 */ 4837 static int command_pid_is_dead; 4838 static void wait_sig (sig) 4839 int sig; 4840 { 4841 int status; 4842 int save_errno = errno; 4843 4844 pid_t r = wait (&status); 4845 if (r == command_pid) 4846 command_pid_is_dead++; 4847 errno = save_errno; 4848 } 4849 #endif /* SUNOS_KLUDGE */ 4850 4851 void 4852 server_cleanup (sig) 4853 int sig; 4854 { 4855 /* Do "rm -rf" on the temp directory. */ 4856 int status; 4857 int save_noexec; 4858 4859 if (buf_to_net != NULL) 4860 { 4861 /* FIXME: If this is not the final call from server, this 4862 could deadlock, because the client might be blocked writing 4863 to us. This should not be a problem in practice, because 4864 we do not generate much output when the client is not 4865 waiting for it. */ 4866 set_block (buf_to_net); 4867 buf_flush (buf_to_net, 1); 4868 4869 /* The calls to buf_shutdown are currently only meaningful 4870 when we are using compression. First we shut down 4871 BUF_FROM_NET. That will pick up the checksum generated 4872 when the client shuts down its buffer. Then, after we have 4873 generated any final output, we shut down BUF_TO_NET. */ 4874 4875 status = buf_shutdown (buf_from_net); 4876 if (status != 0) 4877 { 4878 error (0, status, "shutting down buffer from client"); 4879 buf_flush (buf_to_net, 1); 4880 } 4881 } 4882 4883 if (dont_delete_temp) 4884 { 4885 if (buf_to_net != NULL) 4886 (void) buf_shutdown (buf_to_net); 4887 return; 4888 } 4889 4890 /* What a bogus kludge. This disgusting code makes all kinds of 4891 assumptions about SunOS, and is only for a bug in that system. 4892 So only enable it on Suns. */ 4893 #ifdef SUNOS_KLUDGE 4894 if (command_pid > 0) 4895 { 4896 /* To avoid crashes on SunOS due to bugs in SunOS tmpfs 4897 triggered by the use of rename() in RCS, wait for the 4898 subprocess to die. Unfortunately, this means draining output 4899 while waiting for it to unblock the signal we sent it. Yuck! */ 4900 int status; 4901 pid_t r; 4902 4903 signal (SIGCHLD, wait_sig); 4904 if (sig) 4905 /* Perhaps SIGTERM would be more correct. But the child 4906 process will delay the SIGINT delivery until its own 4907 children have exited. */ 4908 kill (command_pid, SIGINT); 4909 /* The caller may also have sent a signal to command_pid, so 4910 always try waiting. First, though, check and see if it's still 4911 there.... */ 4912 do_waitpid: 4913 r = waitpid (command_pid, &status, WNOHANG); 4914 if (r == 0) 4915 ; 4916 else if (r == command_pid) 4917 command_pid_is_dead++; 4918 else if (r == -1) 4919 switch (errno) 4920 { 4921 case ECHILD: 4922 command_pid_is_dead++; 4923 break; 4924 case EINTR: 4925 goto do_waitpid; 4926 } 4927 else 4928 /* waitpid should always return one of the above values */ 4929 abort (); 4930 while (!command_pid_is_dead) 4931 { 4932 struct timeval timeout; 4933 struct fd_set_wrapper readfds; 4934 char buf[100]; 4935 int i; 4936 4937 /* Use a non-zero timeout to avoid eating up CPU cycles. */ 4938 timeout.tv_sec = 2; 4939 timeout.tv_usec = 0; 4940 readfds = command_fds_to_drain; 4941 switch (select (max_command_fd + 1, &readfds.fds, 4942 (fd_set *)0, (fd_set *)0, 4943 &timeout)) 4944 { 4945 case -1: 4946 if (errno != EINTR) 4947 abort (); 4948 case 0: 4949 /* timeout */ 4950 break; 4951 case 1: 4952 for (i = 0; i <= max_command_fd; i++) 4953 { 4954 if (!FD_ISSET (i, &readfds.fds)) 4955 continue; 4956 /* this fd is non-blocking */ 4957 while (read (i, buf, sizeof (buf)) >= 1) 4958 ; 4959 } 4960 break; 4961 default: 4962 abort (); 4963 } 4964 } 4965 } 4966 #endif /* SUNOS_KLUDGE */ 4967 4968 CVS_CHDIR (Tmpdir); 4969 /* Temporarily clear noexec, so that we clean up our temp directory 4970 regardless of it (this could more cleanly be handled by moving 4971 the noexec check to all the unlink_file_dir callers from 4972 unlink_file_dir itself). */ 4973 save_noexec = noexec; 4974 noexec = 0; 4975 /* FIXME? Would be nice to not ignore errors. But what should we do? 4976 We could try to do this before we shut down the network connection, 4977 and try to notify the client (but the client might not be waiting 4978 for responses). We could try something like syslog() or our own 4979 log file. */ 4980 unlink_file_dir (orig_server_temp_dir); 4981 noexec = save_noexec; 4982 4983 if (buf_to_net != NULL) 4984 (void) buf_shutdown (buf_to_net); 4985 } 4986 4987 int server_active = 0; 4988 int server_expanding = 0; 4989 4990 int 4991 server (argc, argv) 4992 int argc; 4993 char **argv; 4994 { 4995 if (argc == -1) 4996 { 4997 static const char *const msg[] = 4998 { 4999 "Usage: %s %s\n", 5000 " Normally invoked by a cvs client on a remote machine.\n", 5001 NULL 5002 }; 5003 usage (msg); 5004 } 5005 /* Ignore argc and argv. They might be from .cvsrc. */ 5006 5007 buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0, 5008 outbuf_memory_error); 5009 buf_from_net = stdio_buffer_initialize (stdin, 1, outbuf_memory_error); 5010 5011 saved_output = buf_nonio_initialize (outbuf_memory_error); 5012 saved_outerr = buf_nonio_initialize (outbuf_memory_error); 5013 5014 /* Since we're in the server parent process, error should use the 5015 protocol to report error messages. */ 5016 error_use_protocol = 1; 5017 5018 /* OK, now figure out where we stash our temporary files. */ 5019 { 5020 char *p; 5021 5022 /* The code which wants to chdir into server_temp_dir is not set 5023 up to deal with it being a relative path. So give an error 5024 for that case. */ 5025 if (!isabsolute (Tmpdir)) 5026 { 5027 if (alloc_pending (80 + strlen (Tmpdir))) 5028 sprintf (pending_error_text, 5029 "E Value of %s for TMPDIR is not absolute", Tmpdir); 5030 5031 /* FIXME: we would like this error to be persistent, that 5032 is, not cleared by print_pending_error. The current client 5033 will exit as soon as it gets an error, but the protocol spec 5034 does not require a client to do so. */ 5035 } 5036 else 5037 { 5038 int status; 5039 int i = 0; 5040 5041 server_temp_dir = malloc (strlen (Tmpdir) + 80); 5042 if (server_temp_dir == NULL) 5043 { 5044 /* 5045 * Strictly speaking, we're not supposed to output anything 5046 * now. But we're about to exit(), give it a try. 5047 */ 5048 printf ("E Fatal server error, aborting.\n\ 5049 error ENOMEM Virtual memory exhausted.\n"); 5050 5051 /* I'm doing this manually rather than via error_exit () 5052 because I'm not sure whether we want to call server_cleanup. 5053 Needs more investigation.... */ 5054 5055 #ifdef SYSTEM_CLEANUP 5056 /* Hook for OS-specific behavior, for example socket 5057 subsystems on NT and OS2 or dealing with windows 5058 and arguments on Mac. */ 5059 SYSTEM_CLEANUP (); 5060 #endif 5061 5062 exit (EXIT_FAILURE); 5063 } 5064 strcpy (server_temp_dir, Tmpdir); 5065 5066 /* Remove a trailing slash from TMPDIR if present. */ 5067 p = server_temp_dir + strlen (server_temp_dir) - 1; 5068 if (*p == '/') 5069 *p = '\0'; 5070 5071 /* 5072 * I wanted to use cvs-serv/PID, but then you have to worry about 5073 * the permissions on the cvs-serv directory being right. So 5074 * use cvs-servPID. 5075 */ 5076 strcat (server_temp_dir, "/cvs-serv"); 5077 5078 p = server_temp_dir + strlen (server_temp_dir); 5079 sprintf (p, "%ld", (long) getpid ()); 5080 5081 orig_server_temp_dir = server_temp_dir; 5082 5083 /* Create the temporary directory, and set the mode to 5084 700, to discourage random people from tampering with 5085 it. */ 5086 while ((status = mkdir_p (server_temp_dir)) == EEXIST) 5087 { 5088 static const char suffix[] = "abcdefghijklmnopqrstuvwxyz"; 5089 5090 if (i >= sizeof suffix - 1) break; 5091 if (i == 0) p = server_temp_dir + strlen (server_temp_dir); 5092 p[0] = suffix[i++]; 5093 p[1] = '\0'; 5094 } 5095 if (status != 0) 5096 { 5097 if (alloc_pending (80 + strlen (server_temp_dir))) 5098 sprintf (pending_error_text, 5099 "E can't create temporary directory %s", 5100 server_temp_dir); 5101 pending_error = status; 5102 } 5103 #ifndef CHMOD_BROKEN 5104 else if (chmod (server_temp_dir, S_IRWXU) < 0) 5105 { 5106 int save_errno = errno; 5107 if (alloc_pending (80 + strlen (server_temp_dir))) 5108 sprintf (pending_error_text, 5109 "E cannot change permissions on temporary directory %s", 5110 server_temp_dir); 5111 pending_error = save_errno; 5112 } 5113 #endif 5114 else if (CVS_CHDIR (server_temp_dir) < 0) 5115 { 5116 int save_errno = errno; 5117 if (alloc_pending (80 + strlen (server_temp_dir))) 5118 sprintf (pending_error_text, 5119 "E cannot change to temporary directory %s", 5120 server_temp_dir); 5121 pending_error = save_errno; 5122 } 5123 } 5124 } 5125 5126 #ifdef SIGABRT 5127 (void) SIG_register (SIGABRT, server_cleanup); 5128 #endif 5129 #ifdef SIGHUP 5130 (void) SIG_register (SIGHUP, server_cleanup); 5131 #endif 5132 #ifdef SIGINT 5133 (void) SIG_register (SIGINT, server_cleanup); 5134 #endif 5135 #ifdef SIGQUIT 5136 (void) SIG_register (SIGQUIT, server_cleanup); 5137 #endif 5138 #ifdef SIGPIPE 5139 (void) SIG_register (SIGPIPE, server_cleanup); 5140 #endif 5141 #ifdef SIGTERM 5142 (void) SIG_register (SIGTERM, server_cleanup); 5143 #endif 5144 5145 /* Now initialize our argument vector (for arguments from the client). */ 5146 5147 /* Small for testing. */ 5148 argument_vector_size = 1; 5149 argument_vector = 5150 (char **) malloc (argument_vector_size * sizeof (char *)); 5151 if (argument_vector == NULL) 5152 { 5153 /* 5154 * Strictly speaking, we're not supposed to output anything 5155 * now. But we're about to exit(), give it a try. 5156 */ 5157 printf ("E Fatal server error, aborting.\n\ 5158 error ENOMEM Virtual memory exhausted.\n"); 5159 5160 /* I'm doing this manually rather than via error_exit () 5161 because I'm not sure whether we want to call server_cleanup. 5162 Needs more investigation.... */ 5163 5164 #ifdef SYSTEM_CLEANUP 5165 /* Hook for OS-specific behavior, for example socket subsystems on 5166 NT and OS2 or dealing with windows and arguments on Mac. */ 5167 SYSTEM_CLEANUP (); 5168 #endif 5169 5170 exit (EXIT_FAILURE); 5171 } 5172 5173 argument_count = 1; 5174 /* This gets printed if the client supports an option which the 5175 server doesn't, causing the server to print a usage message. 5176 FIXME: probably should be using program_name here. 5177 FIXME: just a nit, I suppose, but the usage message the server 5178 prints isn't literally true--it suggests "cvs server" followed 5179 by options which are for a particular command. Might be nice to 5180 say something like "client apparently supports an option not supported 5181 by this server" or something like that instead of usage message. */ 5182 argument_vector[0] = "cvs server"; 5183 5184 while (1) 5185 { 5186 char *cmd, *orig_cmd; 5187 struct request *rq; 5188 int status; 5189 5190 status = buf_read_line (buf_from_net, &cmd, (int *) NULL); 5191 if (status == -2) 5192 { 5193 buf_output0 (buf_to_net, "E Fatal server error, aborting.\n\ 5194 error ENOMEM Virtual memory exhausted.\n"); 5195 break; 5196 } 5197 if (status != 0) 5198 break; 5199 5200 orig_cmd = cmd; 5201 for (rq = requests; rq->name != NULL; ++rq) 5202 if (strncmp (cmd, rq->name, strlen (rq->name)) == 0) 5203 { 5204 int len = strlen (rq->name); 5205 if (cmd[len] == '\0') 5206 cmd += len; 5207 else if (cmd[len] == ' ') 5208 cmd += len + 1; 5209 else 5210 /* 5211 * The first len characters match, but it's a different 5212 * command. e.g. the command is "cooperate" but we matched 5213 * "co". 5214 */ 5215 continue; 5216 5217 if (!(rq->flags & RQ_ROOTLESS) 5218 && current_parsed_root == NULL) 5219 { 5220 /* For commands which change the way in which data 5221 is sent and received, for example Gzip-stream, 5222 this does the wrong thing. Since the client 5223 assumes that everything is being compressed, 5224 unconditionally, there is no way to give this 5225 error to the client without turning on 5226 compression. The obvious fix would be to make 5227 Gzip-stream RQ_ROOTLESS (with the corresponding 5228 change to the spec), and that might be a good 5229 idea but then again I can see some settings in 5230 CVSROOT about what compression level to allow. 5231 I suppose a more baroque answer would be to 5232 turn on compression (say, at level 1), just 5233 enough to give the "Root request missing" 5234 error. For now we just lose. */ 5235 if (alloc_pending (80)) 5236 sprintf (pending_error_text, 5237 "E Protocol error: Root request missing"); 5238 } 5239 else 5240 (*rq->func) (cmd); 5241 break; 5242 } 5243 if (rq->name == NULL) 5244 { 5245 if (!print_pending_error ()) 5246 { 5247 buf_output0 (buf_to_net, "error unrecognized request `"); 5248 buf_output0 (buf_to_net, cmd); 5249 buf_append_char (buf_to_net, '\''); 5250 buf_append_char (buf_to_net, '\n'); 5251 } 5252 } 5253 free (orig_cmd); 5254 } 5255 server_cleanup (0); 5256 return 0; 5257 } 5258 5259 5260 #if defined (HAVE_KERBEROS) || defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI) 5261 static void switch_to_user PROTO((const char *)); 5262 5263 static void 5264 switch_to_user (username) 5265 const char *username; 5266 { 5267 struct passwd *pw; 5268 5269 pw = getpwnam (username); 5270 if (pw == NULL) 5271 { 5272 /* Normally this won't be reached; check_password contains 5273 a similar check. */ 5274 5275 printf ("E Fatal error, aborting.\n\ 5276 error 0 %s: no such user\n", username); 5277 /* Don't worry about server_cleanup; server_active isn't set yet. */ 5278 error_exit (); 5279 } 5280 5281 #if HAVE_INITGROUPS 5282 if (initgroups (pw->pw_name, pw->pw_gid) < 0 5283 # ifdef EPERM 5284 /* At least on the system I tried, initgroups() only works as root. 5285 But we do still want to report ENOMEM and whatever other 5286 errors initgroups() might dish up. */ 5287 && errno != EPERM 5288 # endif 5289 ) 5290 { 5291 /* This could be a warning, but I'm not sure I see the point 5292 in doing that instead of an error given that it would happen 5293 on every connection. We could log it somewhere and not tell 5294 the user. But at least for now make it an error. */ 5295 printf ("error 0 initgroups failed: %s\n", strerror (errno)); 5296 /* Don't worry about server_cleanup; server_active isn't set yet. */ 5297 error_exit (); 5298 } 5299 #endif /* HAVE_INITGROUPS */ 5300 5301 #ifdef SETXID_SUPPORT 5302 /* honor the setgid bit iff set*/ 5303 if (getgid() != getegid()) 5304 { 5305 if (setgid (getegid ()) < 0) 5306 { 5307 /* See comments at setuid call below for more discussion. */ 5308 printf ("error 0 setgid failed: %s\n", strerror (errno)); 5309 /* Don't worry about server_cleanup; 5310 server_active isn't set yet. */ 5311 error_exit (); 5312 } 5313 } 5314 else 5315 #endif 5316 { 5317 if (setgid (pw->pw_gid) < 0) 5318 { 5319 /* See comments at setuid call below for more discussion. */ 5320 printf ("error 0 setgid failed: %s\n", strerror (errno)); 5321 /* Don't worry about server_cleanup; 5322 server_active isn't set yet. */ 5323 error_exit (); 5324 } 5325 } 5326 5327 if (setuid (pw->pw_uid) < 0) 5328 { 5329 /* Note that this means that if run as a non-root user, 5330 CVSROOT/passwd must contain the user we are running as 5331 (e.g. "joe:FsEfVcu:cvs" if run as "cvs" user). This seems 5332 cleaner than ignoring the error like CVS 1.10 and older but 5333 it does mean that some people might need to update their 5334 CVSROOT/passwd file. */ 5335 printf ("error 0 setuid failed: %s\n", strerror (errno)); 5336 /* Don't worry about server_cleanup; server_active isn't set yet. */ 5337 error_exit (); 5338 } 5339 5340 /* We don't want our umask to change file modes. The modes should 5341 be set by the modes used in the repository, and by the umask of 5342 the client. */ 5343 umask (0); 5344 5345 #ifdef AUTH_SERVER_SUPPORT 5346 /* Make sure our CVS_Username has been set. */ 5347 if (CVS_Username == NULL) 5348 CVS_Username = xstrdup (username); 5349 #endif 5350 5351 #if HAVE_PUTENV 5352 /* Set LOGNAME, USER and CVS_USER in the environment, in case they 5353 are already set to something else. */ 5354 { 5355 char *env; 5356 #ifdef AUTH_SERVER_SUPPORT 5357 char *cvs_user; 5358 #endif 5359 5360 env = xmalloc (sizeof "LOGNAME=" + strlen (username)); 5361 (void) sprintf (env, "LOGNAME=%s", username); 5362 (void) putenv (env); 5363 5364 env = xmalloc (sizeof "USER=" + strlen (username)); 5365 (void) sprintf (env, "USER=%s", username); 5366 (void) putenv (env); 5367 5368 #ifdef AUTH_SERVER_SUPPORT 5369 cvs_user = NULL != CVS_Username ? CVS_Username : ""; 5370 env = xmalloc (sizeof "CVS_USER=" + strlen (cvs_user)); 5371 (void) sprintf (env, "CVS_USER=%s", cvs_user); 5372 (void) putenv (env); 5373 #endif 5374 } 5375 #endif /* HAVE_PUTENV */ 5376 } 5377 #endif 5378 5379 #ifdef AUTH_SERVER_SUPPORT 5380 5381 extern char *crypt PROTO((const char *, const char *)); 5382 5383 5384 /* 5385 * 0 means no entry found for this user. 5386 * 1 means entry found and password matches (or found password is empty) 5387 * 2 means entry found, but password does not match. 5388 * 5389 * If 1, host_user_ptr will be set to point at the system 5390 * username (i.e., the "real" identity, which may or may not be the 5391 * CVS username) of this user; caller may free this. Global 5392 * CVS_Username will point at an allocated copy of cvs username (i.e., 5393 * the username argument below). 5394 * kff todo: FIXME: last sentence is not true, it applies to caller. 5395 */ 5396 static int 5397 check_repository_password (username, password, repository, host_user_ptr) 5398 char *username, *password, *repository, **host_user_ptr; 5399 { 5400 int retval = 0; 5401 FILE *fp; 5402 char *filename; 5403 char *linebuf = NULL; 5404 size_t linebuf_len; 5405 int found_it = 0; 5406 int namelen; 5407 5408 /* We don't use current_parsed_root->directory because it hasn't been set yet 5409 * -- our `repository' argument came from the authentication 5410 * protocol, not the regular CVS protocol. 5411 */ 5412 5413 filename = xmalloc (strlen (repository) 5414 + 1 5415 + strlen (CVSROOTADM) 5416 + 1 5417 + strlen (CVSROOTADM_PASSWD) 5418 + 1); 5419 5420 (void) sprintf (filename, "%s/%s/%s", repository, 5421 CVSROOTADM, CVSROOTADM_PASSWD); 5422 5423 fp = CVS_FOPEN (filename, "r"); 5424 if (fp == NULL) 5425 { 5426 if (!existence_error (errno)) 5427 error (0, errno, "cannot open %s", filename); 5428 return 0; 5429 } 5430 5431 /* Look for a relevant line -- one with this user's name. */ 5432 namelen = strlen (username); 5433 while (getline (&linebuf, &linebuf_len, fp) >= 0) 5434 { 5435 if ((strncmp (linebuf, username, namelen) == 0) 5436 && (linebuf[namelen] == ':')) 5437 { 5438 found_it = 1; 5439 break; 5440 } 5441 } 5442 if (ferror (fp)) 5443 error (0, errno, "cannot read %s", filename); 5444 if (fclose (fp) < 0) 5445 error (0, errno, "cannot close %s", filename); 5446 5447 /* If found_it, then linebuf contains the information we need. */ 5448 if (found_it) 5449 { 5450 char *found_password, *host_user_tmp; 5451 char *non_cvsuser_portion; 5452 5453 /* We need to make sure lines such as 5454 * 5455 * "username::sysuser\n" 5456 * "username:\n" 5457 * "username: \n" 5458 * 5459 * all result in a found_password of NULL, but we also need to 5460 * make sure that 5461 * 5462 * "username: :sysuser\n" 5463 * "username: <whatever>:sysuser\n" 5464 * 5465 * continues to result in an impossible password. That way, 5466 * an admin would be on safe ground by going in and tacking a 5467 * space onto the front of a password to disable the account 5468 * (a technique some people use to close accounts 5469 * temporarily). 5470 */ 5471 5472 /* Make `non_cvsuser_portion' contain everything after the CVS 5473 username, but null out any final newline. */ 5474 non_cvsuser_portion = linebuf + namelen; 5475 strtok (non_cvsuser_portion, "\n"); 5476 5477 /* If there's a colon now, we just want to inch past it. */ 5478 if (strchr (non_cvsuser_portion, ':') == non_cvsuser_portion) 5479 non_cvsuser_portion++; 5480 5481 /* Okay, after this conditional chain, found_password and 5482 host_user_tmp will have useful values: */ 5483 5484 if ((non_cvsuser_portion == NULL) 5485 || (strlen (non_cvsuser_portion) == 0) 5486 || ((strspn (non_cvsuser_portion, " \t")) 5487 == strlen (non_cvsuser_portion))) 5488 { 5489 found_password = NULL; 5490 host_user_tmp = NULL; 5491 } 5492 else if (strncmp (non_cvsuser_portion, ":", 1) == 0) 5493 { 5494 found_password = NULL; 5495 host_user_tmp = non_cvsuser_portion + 1; 5496 if (strlen (host_user_tmp) == 0) 5497 host_user_tmp = NULL; 5498 } 5499 else 5500 { 5501 found_password = strtok (non_cvsuser_portion, ":"); 5502 host_user_tmp = strtok (NULL, ":"); 5503 } 5504 5505 /* Of course, maybe there was no system user portion... */ 5506 if (host_user_tmp == NULL) 5507 host_user_tmp = username; 5508 5509 /* Verify blank passwords directly, otherwise use crypt(). */ 5510 if ((found_password == NULL) 5511 || ((strcmp (found_password, crypt (password, found_password)) 5512 == 0))) 5513 { 5514 /* Give host_user_ptr permanent storage. */ 5515 *host_user_ptr = xstrdup (host_user_tmp); 5516 retval = 1; 5517 } 5518 else 5519 { 5520 *host_user_ptr = NULL; 5521 retval = 2; 5522 } 5523 } 5524 else /* Didn't find this user, so deny access. */ 5525 { 5526 *host_user_ptr = NULL; 5527 retval = 0; 5528 } 5529 5530 free (filename); 5531 if (linebuf) 5532 free (linebuf); 5533 5534 return retval; 5535 } 5536 5537 5538 /* Return a hosting username if password matches, else NULL. */ 5539 static char * 5540 check_password (username, password, repository) 5541 char *username, *password, *repository; 5542 { 5543 int rc; 5544 char *host_user = NULL; 5545 5546 /* First we see if this user has a password in the CVS-specific 5547 password file. If so, that's enough to authenticate with. If 5548 not, we'll check /etc/passwd. */ 5549 5550 rc = check_repository_password (username, password, repository, 5551 &host_user); 5552 5553 if (rc == 2) 5554 return NULL; 5555 5556 /* else */ 5557 5558 if (rc == 1) 5559 { 5560 /* host_user already set by reference, so just return. */ 5561 goto handle_return; 5562 } 5563 else if (rc == 0 && system_auth) 5564 { 5565 /* No cvs password found, so try /etc/passwd. */ 5566 5567 const char *found_passwd = NULL; 5568 struct passwd *pw; 5569 #ifdef HAVE_GETSPNAM 5570 struct spwd *spw; 5571 5572 spw = getspnam (username); 5573 if (spw != NULL) 5574 { 5575 found_passwd = spw->sp_pwdp; 5576 } 5577 #endif 5578 5579 if (found_passwd == NULL && (pw = getpwnam (username)) != NULL) 5580 { 5581 found_passwd = pw->pw_passwd; 5582 } 5583 5584 if (found_passwd == NULL) 5585 { 5586 printf ("E Fatal error, aborting.\n\ 5587 error 0 %s: no such user\n", username); 5588 5589 /* I'm doing this manually rather than via error_exit () 5590 because I'm not sure whether we want to call server_cleanup. 5591 Needs more investigation.... */ 5592 5593 #ifdef SYSTEM_CLEANUP 5594 /* Hook for OS-specific behavior, for example socket subsystems on 5595 NT and OS2 or dealing with windows and arguments on Mac. */ 5596 SYSTEM_CLEANUP (); 5597 #endif 5598 5599 exit (EXIT_FAILURE); 5600 } 5601 5602 if (*found_passwd) 5603 { 5604 /* user exists and has a password */ 5605 host_user = ((! strcmp (found_passwd, 5606 crypt (password, found_passwd))) 5607 ? xstrdup (username) : NULL); 5608 goto handle_return; 5609 } 5610 else if (password && *password) 5611 { 5612 /* user exists and has no system password, but we got 5613 one as parameter */ 5614 host_user = xstrdup (username); 5615 goto handle_return; 5616 } 5617 else 5618 { 5619 /* user exists but has no password at all */ 5620 host_user = NULL; 5621 goto handle_return; 5622 } 5623 } 5624 else if (rc == 0) 5625 { 5626 /* Note that the message _does_ distinguish between the case in 5627 which we check for a system password and the case in which 5628 we do not. It is a real pain to track down why it isn't 5629 letting you in if it won't say why, and I am not convinced 5630 that the potential information disclosure to an attacker 5631 outweighs this. */ 5632 printf ("error 0 no such user %s in CVSROOT/passwd\n", username); 5633 5634 /* I'm doing this manually rather than via error_exit () 5635 because I'm not sure whether we want to call server_cleanup. 5636 Needs more investigation.... */ 5637 5638 #ifdef SYSTEM_CLEANUP 5639 /* Hook for OS-specific behavior, for example socket subsystems on 5640 NT and OS2 or dealing with windows and arguments on Mac. */ 5641 SYSTEM_CLEANUP (); 5642 #endif 5643 exit (EXIT_FAILURE); 5644 } 5645 else 5646 { 5647 /* Something strange happened. We don't know what it was, but 5648 we certainly won't grant authorization. */ 5649 host_user = NULL; 5650 goto handle_return; 5651 } 5652 5653 handle_return: 5654 if (host_user) 5655 { 5656 /* Set CVS_Username here, in allocated space. 5657 It might or might not be the same as host_user. */ 5658 CVS_Username = xmalloc (strlen (username) + 1); 5659 strcpy (CVS_Username, username); 5660 } 5661 5662 return host_user; 5663 } 5664 5665 #endif /* AUTH_SERVER_SUPPORT */ 5666 5667 #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI) 5668 5669 /* Read username and password from client (i.e., stdin). 5670 If correct, then switch to run as that user and send an ACK to the 5671 client via stdout, else send NACK and die. */ 5672 void 5673 pserver_authenticate_connection () 5674 { 5675 char *tmp = NULL; 5676 size_t tmp_allocated = 0; 5677 #ifdef AUTH_SERVER_SUPPORT 5678 char *repository = NULL; 5679 size_t repository_allocated = 0; 5680 char *username = NULL; 5681 size_t username_allocated = 0; 5682 char *password = NULL; 5683 size_t password_allocated = 0; 5684 5685 char *host_user; 5686 char *descrambled_password; 5687 #endif /* AUTH_SERVER_SUPPORT */ 5688 int verify_and_exit = 0; 5689 5690 /* The Authentication Protocol. Client sends: 5691 * 5692 * BEGIN AUTH REQUEST\n 5693 * <REPOSITORY>\n 5694 * <USERNAME>\n 5695 * <PASSWORD>\n 5696 * END AUTH REQUEST\n 5697 * 5698 * Server uses above information to authenticate, then sends 5699 * 5700 * I LOVE YOU\n 5701 * 5702 * if it grants access, else 5703 * 5704 * I HATE YOU\n 5705 * 5706 * if it denies access (and it exits if denying). 5707 * 5708 * When the client is "cvs login", the user does not desire actual 5709 * repository access, but would like to confirm the password with 5710 * the server. In this case, the start and stop strings are 5711 * 5712 * BEGIN VERIFICATION REQUEST\n 5713 * 5714 * and 5715 * 5716 * END VERIFICATION REQUEST\n 5717 * 5718 * On a verification request, the server's responses are the same 5719 * (with the obvious semantics), but it exits immediately after 5720 * sending the response in both cases. 5721 * 5722 * Why is the repository sent? Well, note that the actual 5723 * client/server protocol can't start up until authentication is 5724 * successful. But in order to perform authentication, the server 5725 * needs to look up the password in the special CVS passwd file, 5726 * before trying /etc/passwd. So the client transmits the 5727 * repository as part of the "authentication protocol". The 5728 * repository will be redundantly retransmitted later, but that's no 5729 * big deal. 5730 */ 5731 5732 #ifdef SO_KEEPALIVE 5733 /* Set SO_KEEPALIVE on the socket, so that we don't hang forever 5734 if the client dies while we are waiting for input. */ 5735 { 5736 int on = 1; 5737 5738 if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, 5739 (char *) &on, sizeof on) < 0) 5740 { 5741 #ifdef HAVE_SYSLOG_H 5742 syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m"); 5743 #endif 5744 } 5745 } 5746 #endif 5747 5748 /* Make sure the protocol starts off on the right foot... */ 5749 if (getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX) < 0) 5750 /* FIXME: what? We could try writing error/eof, but chances 5751 are the network connection is dead bidirectionally. log it 5752 somewhere? */ 5753 ; 5754 5755 if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0) 5756 verify_and_exit = 1; 5757 else if (strcmp (tmp, "BEGIN AUTH REQUEST\n") == 0) 5758 ; 5759 else if (strcmp (tmp, "BEGIN GSSAPI REQUEST\n") == 0) 5760 { 5761 #ifdef HAVE_GSSAPI 5762 free (tmp); 5763 gserver_authenticate_connection (); 5764 return; 5765 #else 5766 error (1, 0, "GSSAPI authentication not supported by this server"); 5767 #endif 5768 } 5769 else 5770 error (1, 0, "bad auth protocol start: %s", tmp); 5771 5772 #ifndef AUTH_SERVER_SUPPORT 5773 5774 error (1, 0, "Password authentication not supported by this server"); 5775 5776 #else /* AUTH_SERVER_SUPPORT */ 5777 5778 /* Get the three important pieces of information in order. */ 5779 /* See above comment about error handling. */ 5780 getline_safe (&repository, &repository_allocated, stdin, PATH_MAX); 5781 getline_safe (&username, &username_allocated, stdin, PATH_MAX); 5782 getline_safe (&password, &password_allocated, stdin, PATH_MAX); 5783 5784 /* Make them pure. */ 5785 strip_trailing_newlines (repository); 5786 strip_trailing_newlines (username); 5787 strip_trailing_newlines (password); 5788 5789 /* ... and make sure the protocol ends on the right foot. */ 5790 /* See above comment about error handling. */ 5791 getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX); 5792 if (strcmp (tmp, 5793 verify_and_exit ? 5794 "END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n") 5795 != 0) 5796 { 5797 error (1, 0, "bad auth protocol end: %s", tmp); 5798 } 5799 if (!root_allow_ok (repository)) 5800 { 5801 printf ("error 0 %s: no such repository\n", repository); 5802 #ifdef HAVE_SYSLOG_H 5803 syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository); 5804 #endif 5805 goto i_hate_you; 5806 } 5807 5808 /* OK, now parse the config file, so we can use it to control how 5809 to check passwords. If there was an error parsing the config 5810 file, parse_config already printed an error. We keep going. 5811 Why? Because if we didn't, then there would be no way to check 5812 in a new CVSROOT/config file to fix the broken one! */ 5813 parse_config (repository); 5814 5815 /* We need the real cleartext before we hash it. */ 5816 descrambled_password = descramble (password); 5817 host_user = check_password (username, descrambled_password, repository); 5818 memset (descrambled_password, 0, strlen (descrambled_password)); 5819 free (descrambled_password); 5820 if (host_user == NULL) 5821 { 5822 #ifdef HAVE_SYSLOG_H 5823 syslog (LOG_DAEMON | LOG_NOTICE, "login failure (for %s)", repository); 5824 #ifdef LOG_AUTHPRIV 5825 syslog (LOG_AUTHPRIV | LOG_NOTICE, "login failure by %s / %s (for %s)", 5826 username, descrambled_password, repository); 5827 #endif 5828 #endif 5829 i_hate_you: 5830 printf ("I HATE YOU\n"); 5831 fflush (stdout); 5832 5833 /* Don't worry about server_cleanup, server_active isn't set 5834 yet. */ 5835 error_exit (); 5836 } 5837 5838 /* Don't go any farther if we're just responding to "cvs login". */ 5839 if (verify_and_exit) 5840 { 5841 printf ("I LOVE YOU\n"); 5842 fflush (stdout); 5843 5844 #ifdef SYSTEM_CLEANUP 5845 /* Hook for OS-specific behavior, for example socket subsystems on 5846 NT and OS2 or dealing with windows and arguments on Mac. */ 5847 SYSTEM_CLEANUP (); 5848 #endif 5849 5850 exit (0); 5851 } 5852 5853 /* Set Pserver_Repos so that we can check later that the same 5854 repository is sent in later client/server protocol. */ 5855 Pserver_Repos = xmalloc (strlen (repository) + 1); 5856 strcpy (Pserver_Repos, repository); 5857 5858 /* Switch to run as this user. */ 5859 switch_to_user (host_user); 5860 free (host_user); 5861 free (tmp); 5862 free (repository); 5863 free (username); 5864 free (password); 5865 5866 printf ("I LOVE YOU\n"); 5867 fflush (stdout); 5868 #endif /* AUTH_SERVER_SUPPORT */ 5869 } 5870 5871 #endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */ 5872 5873 5874 #ifdef HAVE_KERBEROS 5875 void 5876 kserver_authenticate_connection () 5877 { 5878 int status; 5879 char instance[INST_SZ]; 5880 struct sockaddr_in peer; 5881 struct sockaddr_in laddr; 5882 int len; 5883 KTEXT_ST ticket; 5884 AUTH_DAT auth; 5885 char version[KRB_SENDAUTH_VLEN]; 5886 char user[ANAME_SZ]; 5887 5888 strcpy (instance, "*"); 5889 len = sizeof peer; 5890 if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &len) < 0 5891 || getsockname (STDIN_FILENO, (struct sockaddr *) &laddr, 5892 &len) < 0) 5893 { 5894 printf ("E Fatal error, aborting.\n\ 5895 error %s getpeername or getsockname failed\n", strerror (errno)); 5896 #ifdef SYSTEM_CLEANUP 5897 /* Hook for OS-specific behavior, for example socket subsystems on 5898 NT and OS2 or dealing with windows and arguments on Mac. */ 5899 SYSTEM_CLEANUP (); 5900 #endif 5901 exit (EXIT_FAILURE); 5902 } 5903 5904 #ifdef SO_KEEPALIVE 5905 /* Set SO_KEEPALIVE on the socket, so that we don't hang forever 5906 if the client dies while we are waiting for input. */ 5907 { 5908 int on = 1; 5909 5910 if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, 5911 (char *) &on, sizeof on) < 0) 5912 { 5913 #ifdef HAVE_SYSLOG_H 5914 syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m"); 5915 #endif 5916 } 5917 } 5918 #endif 5919 5920 status = krb_recvauth (KOPT_DO_MUTUAL, STDIN_FILENO, &ticket, "rcmd", 5921 instance, &peer, &laddr, &auth, "", sched, 5922 version); 5923 if (status != KSUCCESS) 5924 { 5925 printf ("E Fatal error, aborting.\n\ 5926 error 0 kerberos: %s\n", krb_get_err_text(status)); 5927 #ifdef SYSTEM_CLEANUP 5928 /* Hook for OS-specific behavior, for example socket subsystems on 5929 NT and OS2 or dealing with windows and arguments on Mac. */ 5930 SYSTEM_CLEANUP (); 5931 #endif 5932 exit (EXIT_FAILURE); 5933 } 5934 5935 memcpy (kblock, auth.session, sizeof (C_Block)); 5936 5937 /* Get the local name. */ 5938 status = krb_kntoln (&auth, user); 5939 if (status != KSUCCESS) 5940 { 5941 printf ("E Fatal error, aborting.\n\ 5942 error 0 kerberos: can't get local name: %s\n", krb_get_err_text(status)); 5943 #ifdef SYSTEM_CLEANUP 5944 /* Hook for OS-specific behavior, for example socket subsystems on 5945 NT and OS2 or dealing with windows and arguments on Mac. */ 5946 SYSTEM_CLEANUP (); 5947 #endif 5948 exit (EXIT_FAILURE); 5949 } 5950 5951 /* Switch to run as this user. */ 5952 switch_to_user (user); 5953 } 5954 #endif /* HAVE_KERBEROS */ 5955 5956 #ifdef HAVE_GSSAPI 5957 5958 #ifndef MAXHOSTNAMELEN 5959 #define MAXHOSTNAMELEN (256) 5960 #endif 5961 5962 /* Authenticate a GSSAPI connection. This is called from 5963 pserver_authenticate_connection, and it handles success and failure 5964 the same way. */ 5965 5966 static void 5967 gserver_authenticate_connection () 5968 { 5969 char hostname[MAXHOSTNAMELEN]; 5970 struct hostent *hp; 5971 gss_buffer_desc tok_in, tok_out; 5972 char buf[1024]; 5973 OM_uint32 stat_min, ret; 5974 gss_name_t server_name, client_name; 5975 gss_cred_id_t server_creds; 5976 int nbytes; 5977 gss_OID mechid; 5978 5979 gethostname (hostname, sizeof hostname); 5980 hp = gethostbyname (hostname); 5981 if (hp == NULL) 5982 error (1, 0, "can't get canonical hostname"); 5983 5984 sprintf (buf, "cvs@%s", hp->h_name); 5985 tok_in.value = buf; 5986 tok_in.length = strlen (buf); 5987 5988 if (gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE, 5989 &server_name) != GSS_S_COMPLETE) 5990 error (1, 0, "could not import GSSAPI service name %s", buf); 5991 5992 /* Acquire the server credential to verify the client's 5993 authentication. */ 5994 if (gss_acquire_cred (&stat_min, server_name, 0, GSS_C_NULL_OID_SET, 5995 GSS_C_ACCEPT, &server_creds, 5996 NULL, NULL) != GSS_S_COMPLETE) 5997 error (1, 0, "could not acquire GSSAPI server credentials"); 5998 5999 gss_release_name (&stat_min, &server_name); 6000 6001 /* The client will send us a two byte length followed by that many 6002 bytes. */ 6003 if (fread (buf, 1, 2, stdin) != 2) 6004 error (1, errno, "read of length failed"); 6005 6006 nbytes = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff); 6007 assert (nbytes <= sizeof buf); 6008 6009 if (fread (buf, 1, nbytes, stdin) != nbytes) 6010 error (1, errno, "read of data failed"); 6011 6012 gcontext = GSS_C_NO_CONTEXT; 6013 tok_in.length = nbytes; 6014 tok_in.value = buf; 6015 6016 if (gss_accept_sec_context (&stat_min, 6017 &gcontext, /* context_handle */ 6018 server_creds, /* verifier_cred_handle */ 6019 &tok_in, /* input_token */ 6020 NULL, /* channel bindings */ 6021 &client_name, /* src_name */ 6022 &mechid, /* mech_type */ 6023 &tok_out, /* output_token */ 6024 &ret, 6025 NULL, /* ignore time_rec */ 6026 NULL) /* ignore del_cred_handle */ 6027 != GSS_S_COMPLETE) 6028 { 6029 error (1, 0, "could not verify credentials"); 6030 } 6031 6032 /* FIXME: Use Kerberos v5 specific code to authenticate to a user. 6033 We could instead use an authentication to access mapping. */ 6034 { 6035 krb5_context kc; 6036 krb5_principal p; 6037 gss_buffer_desc desc; 6038 6039 krb5_init_context (&kc); 6040 if (gss_display_name (&stat_min, client_name, &desc, 6041 &mechid) != GSS_S_COMPLETE 6042 || krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0 6043 || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0 6044 || krb5_kuserok (kc, p, buf) != TRUE) 6045 { 6046 error (1, 0, "access denied"); 6047 } 6048 krb5_free_principal (kc, p); 6049 krb5_free_context (kc); 6050 } 6051 6052 if (tok_out.length != 0) 6053 { 6054 char cbuf[2]; 6055 6056 cbuf[0] = (tok_out.length >> 8) & 0xff; 6057 cbuf[1] = tok_out.length & 0xff; 6058 if (fwrite (cbuf, 1, 2, stdout) != 2 6059 || (fwrite (tok_out.value, 1, tok_out.length, stdout) 6060 != tok_out.length)) 6061 error (1, errno, "fwrite failed"); 6062 } 6063 6064 switch_to_user (buf); 6065 6066 printf ("I LOVE YOU\n"); 6067 fflush (stdout); 6068 } 6069 6070 #endif /* HAVE_GSSAPI */ 6071 6072 #endif /* SERVER_SUPPORT */ 6073 6074 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT) 6075 6076 /* This global variable is non-zero if the user requests encryption on 6077 the command line. */ 6078 int cvsencrypt; 6079 6080 /* This global variable is non-zero if the users requests stream 6081 authentication on the command line. */ 6082 int cvsauthenticate; 6083 6084 #ifdef HAVE_GSSAPI 6085 6086 /* An buffer interface using GSSAPI. This is built on top of a 6087 packetizing buffer. */ 6088 6089 /* This structure is the closure field of the GSSAPI translation 6090 routines. */ 6091 6092 struct cvs_gssapi_wrap_data 6093 { 6094 /* The GSSAPI context. */ 6095 gss_ctx_id_t gcontext; 6096 }; 6097 6098 static int cvs_gssapi_wrap_input PROTO((void *, const char *, char *, int)); 6099 static int cvs_gssapi_wrap_output PROTO((void *, const char *, char *, int, 6100 int *)); 6101 6102 /* Create a GSSAPI wrapping buffer. We use a packetizing buffer with 6103 GSSAPI wrapping routines. */ 6104 6105 struct buffer * 6106 cvs_gssapi_wrap_buffer_initialize (buf, input, gcontext, memory) 6107 struct buffer *buf; 6108 int input; 6109 gss_ctx_id_t gcontext; 6110 void (*memory) PROTO((struct buffer *)); 6111 { 6112 struct cvs_gssapi_wrap_data *gd; 6113 6114 gd = (struct cvs_gssapi_wrap_data *) xmalloc (sizeof *gd); 6115 gd->gcontext = gcontext; 6116 6117 return (packetizing_buffer_initialize 6118 (buf, 6119 input ? cvs_gssapi_wrap_input : NULL, 6120 input ? NULL : cvs_gssapi_wrap_output, 6121 gd, 6122 memory)); 6123 } 6124 6125 /* Unwrap data using GSSAPI. */ 6126 6127 static int 6128 cvs_gssapi_wrap_input (fnclosure, input, output, size) 6129 void *fnclosure; 6130 const char *input; 6131 char *output; 6132 int size; 6133 { 6134 struct cvs_gssapi_wrap_data *gd = 6135 (struct cvs_gssapi_wrap_data *) fnclosure; 6136 gss_buffer_desc inbuf, outbuf; 6137 OM_uint32 stat_min; 6138 int conf; 6139 6140 inbuf.value = (void *) input; 6141 inbuf.length = size; 6142 6143 if (gss_unwrap (&stat_min, gd->gcontext, &inbuf, &outbuf, &conf, NULL) 6144 != GSS_S_COMPLETE) 6145 { 6146 error (1, 0, "gss_unwrap failed"); 6147 } 6148 6149 if (outbuf.length > size) 6150 abort (); 6151 6152 memcpy (output, outbuf.value, outbuf.length); 6153 6154 /* The real packet size is stored in the data, so we don't need to 6155 remember outbuf.length. */ 6156 6157 gss_release_buffer (&stat_min, &outbuf); 6158 6159 return 0; 6160 } 6161 6162 /* Wrap data using GSSAPI. */ 6163 6164 static int 6165 cvs_gssapi_wrap_output (fnclosure, input, output, size, translated) 6166 void *fnclosure; 6167 const char *input; 6168 char *output; 6169 int size; 6170 int *translated; 6171 { 6172 struct cvs_gssapi_wrap_data *gd = 6173 (struct cvs_gssapi_wrap_data *) fnclosure; 6174 gss_buffer_desc inbuf, outbuf; 6175 OM_uint32 stat_min; 6176 int conf_req, conf; 6177 6178 inbuf.value = (void *) input; 6179 inbuf.length = size; 6180 6181 #ifdef ENCRYPTION 6182 conf_req = cvs_gssapi_encrypt; 6183 #else 6184 conf_req = 0; 6185 #endif 6186 6187 if (gss_wrap (&stat_min, gd->gcontext, conf_req, GSS_C_QOP_DEFAULT, 6188 &inbuf, &conf, &outbuf) != GSS_S_COMPLETE) 6189 error (1, 0, "gss_wrap failed"); 6190 6191 /* The packetizing buffer only permits us to add 100 bytes. 6192 FIXME: I don't know what, if anything, is guaranteed by GSSAPI. 6193 This may need to be increased for a different GSSAPI 6194 implementation, or we may need a different algorithm. */ 6195 if (outbuf.length > size + 100) 6196 abort (); 6197 6198 memcpy (output, outbuf.value, outbuf.length); 6199 6200 *translated = outbuf.length; 6201 6202 gss_release_buffer (&stat_min, &outbuf); 6203 6204 return 0; 6205 } 6206 6207 #endif /* HAVE_GSSAPI */ 6208 6209 #ifdef ENCRYPTION 6210 6211 #ifdef HAVE_KERBEROS 6212 6213 /* An encryption interface using Kerberos. This is built on top of a 6214 packetizing buffer. */ 6215 6216 /* This structure is the closure field of the Kerberos translation 6217 routines. */ 6218 6219 struct krb_encrypt_data 6220 { 6221 /* The Kerberos key schedule. */ 6222 Key_schedule sched; 6223 /* The Kerberos DES block. */ 6224 C_Block block; 6225 }; 6226 6227 static int krb_encrypt_input PROTO((void *, const char *, char *, int)); 6228 static int krb_encrypt_output PROTO((void *, const char *, char *, int, 6229 int *)); 6230 6231 /* Create a Kerberos encryption buffer. We use a packetizing buffer 6232 with Kerberos encryption translation routines. */ 6233 6234 struct buffer * 6235 krb_encrypt_buffer_initialize (buf, input, sched, block, memory) 6236 struct buffer *buf; 6237 int input; 6238 Key_schedule sched; 6239 C_Block block; 6240 void (*memory) PROTO((struct buffer *)); 6241 { 6242 struct krb_encrypt_data *kd; 6243 6244 kd = (struct krb_encrypt_data *) xmalloc (sizeof *kd); 6245 memcpy (kd->sched, sched, sizeof (Key_schedule)); 6246 memcpy (kd->block, block, sizeof (C_Block)); 6247 6248 return packetizing_buffer_initialize (buf, 6249 input ? krb_encrypt_input : NULL, 6250 input ? NULL : krb_encrypt_output, 6251 kd, 6252 memory); 6253 } 6254 6255 /* Decrypt Kerberos data. */ 6256 6257 static int 6258 krb_encrypt_input (fnclosure, input, output, size) 6259 void *fnclosure; 6260 const char *input; 6261 char *output; 6262 int size; 6263 { 6264 struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure; 6265 int tcount; 6266 6267 des_cbc_encrypt ((C_Block *) input, (C_Block *) output, 6268 size, kd->sched, &kd->block, 0); 6269 6270 /* SIZE is the size of the buffer, which is set by the encryption 6271 routine. The packetizing buffer will arrange for the first two 6272 bytes in the decrypted buffer to be the real (unaligned) 6273 length. As a safety check, make sure that the length in the 6274 buffer corresponds to SIZE. Note that the length in the buffer 6275 is just the length of the data. We must add 2 to account for 6276 the buffer count itself. */ 6277 tcount = ((output[0] & 0xff) << 8) + (output[1] & 0xff); 6278 if (((tcount + 2 + 7) & ~7) != size) 6279 error (1, 0, "Decryption failure"); 6280 6281 return 0; 6282 } 6283 6284 /* Encrypt Kerberos data. */ 6285 6286 static int 6287 krb_encrypt_output (fnclosure, input, output, size, translated) 6288 void *fnclosure; 6289 const char *input; 6290 char *output; 6291 int size; 6292 int *translated; 6293 { 6294 struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure; 6295 int aligned; 6296 6297 /* For security against a known plaintext attack, we should 6298 initialize any padding bytes to random values. Instead, we 6299 just pick up whatever is on the stack, which is at least better 6300 than using zero. */ 6301 6302 /* Align SIZE to an 8 byte boundary. Note that SIZE includes the 6303 two byte buffer count at the start of INPUT which was added by 6304 the packetizing buffer. */ 6305 aligned = (size + 7) & ~7; 6306 6307 /* We use des_cbc_encrypt rather than krb_mk_priv because the 6308 latter sticks a timestamp in the block, and krb_rd_priv expects 6309 that timestamp to be within five minutes of the current time. 6310 Given the way the CVS server buffers up data, that can easily 6311 fail over a long network connection. We trust krb_recvauth to 6312 guard against a replay attack. */ 6313 6314 des_cbc_encrypt ((C_Block *) input, (C_Block *) output, aligned, 6315 kd->sched, &kd->block, 1); 6316 6317 *translated = aligned; 6318 6319 return 0; 6320 } 6321 6322 #endif /* HAVE_KERBEROS */ 6323 #endif /* ENCRYPTION */ 6324 #endif /* defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT) */ 6325 6326 /* Output LEN bytes at STR. If LEN is zero, then output up to (not including) 6327 the first '\0' byte. */ 6328 6329 void 6330 cvs_output (str, len) 6331 const char *str; 6332 size_t len; 6333 { 6334 if (len == 0) 6335 len = strlen (str); 6336 #ifdef SERVER_SUPPORT 6337 if (error_use_protocol) 6338 { 6339 buf_output (saved_output, str, len); 6340 buf_copy_lines (buf_to_net, saved_output, 'M'); 6341 } 6342 else if (server_active) 6343 { 6344 buf_output (saved_output, str, len); 6345 buf_copy_lines (protocol, saved_output, 'M'); 6346 buf_send_counted (protocol); 6347 } 6348 else 6349 #endif 6350 { 6351 size_t written; 6352 size_t to_write = len; 6353 const char *p = str; 6354 6355 /* For symmetry with cvs_outerr we would call fflush (stderr) 6356 here. I guess the assumption is that stderr will be 6357 unbuffered, so we don't need to. That sounds like a sound 6358 assumption from the manpage I looked at, but if there was 6359 something fishy about it, my guess is that calling fflush 6360 would not produce a significant performance problem. */ 6361 6362 while (to_write > 0) 6363 { 6364 written = fwrite (p, 1, to_write, stdout); 6365 if (written == 0) 6366 break; 6367 p += written; 6368 to_write -= written; 6369 } 6370 } 6371 } 6372 6373 /* Output LEN bytes at STR in binary mode. If LEN is zero, then 6374 output zero bytes. */ 6375 6376 void 6377 cvs_output_binary (str, len) 6378 char *str; 6379 size_t len; 6380 { 6381 #ifdef SERVER_SUPPORT 6382 if (error_use_protocol || server_active) 6383 { 6384 struct buffer *buf; 6385 char size_text[40]; 6386 6387 if (error_use_protocol) 6388 buf = buf_to_net; 6389 else 6390 buf = protocol; 6391 6392 if (!supported_response ("Mbinary")) 6393 { 6394 error (0, 0, "\ 6395 this client does not support writing binary files to stdout"); 6396 return; 6397 } 6398 6399 buf_output0 (buf, "Mbinary\012"); 6400 sprintf (size_text, "%lu\012", (unsigned long) len); 6401 buf_output0 (buf, size_text); 6402 6403 /* Not sure what would be involved in using buf_append_data here 6404 without stepping on the toes of our caller (which is responsible 6405 for the memory allocation of STR). */ 6406 buf_output (buf, str, len); 6407 6408 if (!error_use_protocol) 6409 buf_send_counted (protocol); 6410 } 6411 else 6412 #endif 6413 { 6414 size_t written; 6415 size_t to_write = len; 6416 const char *p = str; 6417 6418 /* For symmetry with cvs_outerr we would call fflush (stderr) 6419 here. I guess the assumption is that stderr will be 6420 unbuffered, so we don't need to. That sounds like a sound 6421 assumption from the manpage I looked at, but if there was 6422 something fishy about it, my guess is that calling fflush 6423 would not produce a significant performance problem. */ 6424 #ifdef USE_SETMODE_STDOUT 6425 int oldmode; 6426 6427 /* It is possible that this should be the same ifdef as 6428 USE_SETMODE_BINARY but at least for the moment we keep them 6429 separate. Mostly this is just laziness and/or a question 6430 of what has been tested where. Also there might be an 6431 issue of setmode vs. _setmode. */ 6432 /* The Windows doc says to call setmode only right after startup. 6433 I assume that what they are talking about can also be helped 6434 by flushing the stream before changing the mode. */ 6435 fflush (stdout); 6436 oldmode = _setmode (_fileno (stdout), OPEN_BINARY); 6437 if (oldmode < 0) 6438 error (0, errno, "failed to setmode on stdout"); 6439 #endif 6440 6441 while (to_write > 0) 6442 { 6443 written = fwrite (p, 1, to_write, stdout); 6444 if (written == 0) 6445 break; 6446 p += written; 6447 to_write -= written; 6448 } 6449 #ifdef USE_SETMODE_STDOUT 6450 fflush (stdout); 6451 if (_setmode (_fileno (stdout), oldmode) != OPEN_BINARY) 6452 error (0, errno, "failed to setmode on stdout"); 6453 #endif 6454 } 6455 } 6456 6457 /* Like CVS_OUTPUT but output is for stderr not stdout. */ 6458 6459 void 6460 cvs_outerr (str, len) 6461 const char *str; 6462 size_t len; 6463 { 6464 if (len == 0) 6465 len = strlen (str); 6466 #ifdef SERVER_SUPPORT 6467 if (error_use_protocol) 6468 { 6469 buf_output (saved_outerr, str, len); 6470 buf_copy_lines (buf_to_net, saved_outerr, 'E'); 6471 } 6472 else if (server_active) 6473 { 6474 buf_output (saved_outerr, str, len); 6475 buf_copy_lines (protocol, saved_outerr, 'E'); 6476 buf_send_counted (protocol); 6477 } 6478 else 6479 #endif 6480 { 6481 size_t written; 6482 size_t to_write = len; 6483 const char *p = str; 6484 6485 /* Make sure that output appears in order if stdout and stderr 6486 point to the same place. For the server case this is taken 6487 care of by the fact that saved_outerr always holds less 6488 than a line. */ 6489 fflush (stdout); 6490 6491 while (to_write > 0) 6492 { 6493 written = fwrite (p, 1, to_write, stderr); 6494 if (written == 0) 6495 break; 6496 p += written; 6497 to_write -= written; 6498 } 6499 } 6500 } 6501 6502 /* Flush stderr. stderr is normally flushed automatically, of course, 6503 but this function is used to flush information from the server back 6504 to the client. */ 6505 6506 void 6507 cvs_flusherr () 6508 { 6509 #ifdef SERVER_SUPPORT 6510 if (error_use_protocol) 6511 { 6512 /* skip the actual stderr flush in this case since the parent process 6513 * on the server should only be writing to stdout anyhow 6514 */ 6515 /* Flush what we can to the network, but don't block. */ 6516 buf_flush (buf_to_net, 0); 6517 } 6518 else if (server_active) 6519 { 6520 /* make sure stderr is flushed before we send the flush count on the 6521 * protocol pipe 6522 */ 6523 fflush (stderr); 6524 /* Send a special count to tell the parent to flush. */ 6525 buf_send_special_count (protocol, -2); 6526 } 6527 else 6528 #endif 6529 fflush (stderr); 6530 } 6531 6532 /* Make it possible for the user to see what has been written to 6533 stdout (it is up to the implementation to decide exactly how far it 6534 should go to ensure this). */ 6535 6536 void 6537 cvs_flushout () 6538 { 6539 #ifdef SERVER_SUPPORT 6540 if (error_use_protocol) 6541 { 6542 /* Flush what we can to the network, but don't block. */ 6543 buf_flush (buf_to_net, 0); 6544 } 6545 else if (server_active) 6546 { 6547 /* Just do nothing. This is because the code which 6548 cvs_flushout replaces, setting stdout to line buffering in 6549 main.c, didn't get called in the server child process. But 6550 in the future it is quite plausible that we'll want to make 6551 this case work analogously to cvs_flusherr. 6552 6553 FIXME - DRP - I tried to implement this and triggered the following 6554 error: "Protocol error: uncounted data discarded". I don't need 6555 this feature right now, so I'm not going to bother with it yet. 6556 */ 6557 buf_send_special_count (protocol, -1); 6558 } 6559 else 6560 #endif 6561 fflush (stdout); 6562 } 6563 6564 /* Output TEXT, tagging it according to TAG. There are lots more 6565 details about what TAG means in cvsclient.texi but for the simple 6566 case (e.g. non-client/server), TAG is just "newline" to output a 6567 newline (in which case TEXT must be NULL), and any other tag to 6568 output normal text. 6569 6570 Note that there is no way to output either \0 or \n as part of TEXT. */ 6571 6572 void 6573 cvs_output_tagged (tag, text) 6574 char *tag; 6575 char *text; 6576 { 6577 if (text != NULL && strchr (text, '\n') != NULL) 6578 /* Uh oh. The protocol has no way to cope with this. For now 6579 we dump core, although that really isn't such a nice 6580 response given that this probably can be caused by newlines 6581 in filenames and other causes other than bugs in CVS. Note 6582 that we don't want to turn this into "MT newline" because 6583 this case is a newline within a tagged item, not a newline 6584 as extraneous sugar for the user. */ 6585 assert (0); 6586 6587 /* Start and end tags don't take any text, per cvsclient.texi. */ 6588 if (tag[0] == '+' || tag[0] == '-') 6589 assert (text == NULL); 6590 6591 #ifdef SERVER_SUPPORT 6592 if (server_active && supported_response ("MT")) 6593 { 6594 struct buffer *buf; 6595 6596 if (error_use_protocol) 6597 buf = buf_to_net; 6598 else 6599 buf = protocol; 6600 6601 buf_output0 (buf, "MT "); 6602 buf_output0 (buf, tag); 6603 if (text != NULL) 6604 { 6605 buf_output (buf, " ", 1); 6606 buf_output0 (buf, text); 6607 } 6608 buf_output (buf, "\n", 1); 6609 6610 if (!error_use_protocol) 6611 buf_send_counted (protocol); 6612 } 6613 else 6614 #endif 6615 { 6616 if (strcmp (tag, "newline") == 0) 6617 cvs_output ("\n", 1); 6618 else if (text != NULL) 6619 cvs_output (text, 0); 6620 } 6621 } 6622