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