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