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