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