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