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)
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. */
23 __RCSID("$MirOS: src/gnu/usr.bin/cvs/src/server.c,v 1.13 2017/04/18 22:45:01 tg Exp $");
25 int server_active = 0;
27 #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
29 # include "log-buffer.h"
30 # include "ms-buffer.h"
31 #endif /* defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) */
33 #if defined (HAVE_GSSAPI) && defined (SERVER_SUPPORT)
34 # include "canon-host.h"
35 # include "gssapi-client.h"
37 /* This stuff isn't included solely with SERVER_SUPPORT since some of these
38 * functions (encryption & the like) get compiled with or without server
41 * FIXME - They should be in a different file.
43 /* We use Kerberos 5 routines to map the GSSAPI credential to a user
47 static void gserver_authenticate_connection (void);
49 /* Whether we are already wrapping GSSAPI communication. */
50 static int cvs_gssapi_wrapping;
52 #endif /* defined (HAVE_GSSAPI) && defined (SERVER_SUPPORT) */
56 extern char *server_hostname;
58 # if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
59 # include <sys/socket.h>
64 # ifndef LOG_DAEMON /* for ancient syslogs */
67 # endif /* HAVE_SYSLOG_H */
70 # include <netinet/in.h>
72 # ifndef HAVE_KRB_GET_ERR_TEXT
73 # define krb_get_err_text(status) krb_err_txt[status]
76 /* Information we need if we are going to use Kerberos encryption. */
77 static C_Block kblock;
78 static Key_schedule sched;
80 # endif /* HAVE_KERBEROS */
86 # include <netinet/tcp.h>
89 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
93 # define O_NONBLOCK O_NDELAY
96 /* For initgroups(). */
99 # endif /* HAVE_INITGROUPS */
101 # ifdef AUTH_SERVER_SUPPORT
103 # ifdef HAVE_GETSPNAM
107 /* The cvs username sent by the client, which might or might not be
108 the same as the system username the server eventually switches to
109 run as. CVS_Username gets set iff password authentication is
111 char *CVS_Username = NULL;
113 /* Used to check that same repos is transmitted in pserver auth and in
114 later CVS protocol. Exported because root.c also uses. */
115 static char *Pserver_Repos = NULL;
117 # endif /* AUTH_SERVER_SUPPORT */
120 # if defined(HAVE_SECURITY_PAM_APPL_H)
121 # include <security/pam_appl.h>
122 # elif defined(HAVE_PAM_PAM_APPL_H)
123 # include <pam/pam_appl.h>
126 static pam_handle_t *pamh = NULL;
128 static char *pam_username;
129 static char *pam_password;
130 # endif /* HAVE_PAM */
134 /* While processing requests, this buffer accumulates data to be sent to
135 the client, and then once we are in do_cvs_command, we use it
136 for all the data to be sent. */
137 static struct buffer *buf_to_net;
139 /* This buffer is used to read input from the client. */
140 static struct buffer *buf_from_net;
144 # ifdef PROXY_SUPPORT
145 /* These are the secondary log buffers so that we can disable them after
146 * creation, when it is determined that they are unneeded, regardless of what
147 * other filters have been prepended to the buffer chain.
149 static struct buffer *proxy_log;
150 static struct buffer *proxy_log_out;
152 /* Set while we are reprocessing a log so that we can avoid sending responses
153 * to some requests twice.
155 static bool reprocessing;
156 # endif /* PROXY_SUPPORT */
160 /* Arguments storage for `Argument' & `Argumentx' requests. */
161 static int argument_count;
162 static char **argument_vector;
163 static int argument_vector_size;
166 * This is where we stash stuff we are going to use. Format string
167 * which expects a single directory within it, starting with a slash.
169 static char *server_temp_dir;
171 /* This is the original value of server_temp_dir, before any possible
172 changes inserted by serve_max_dotdot. */
173 static char *orig_server_temp_dir;
175 /* Nonzero if we should keep the temp directory around after we exit. */
176 static int dont_delete_temp;
178 static void server_write_entries (void);
184 /* Populate all of the directories between BASE_DIR and its relative
185 subdirectory DIR with CVSADM directories. Return 0 for success or
188 create_adm_p (char *base_dir, char *dir)
190 char *dir_where_cvsadm_lives, *dir_to_register, *p, *tmp;
194 if (strcmp (dir, ".") == 0)
195 return 0; /* nothing to do */
197 /* Allocate some space for our directory-munging string. */
198 p = xmalloc (strlen (dir) + 1);
202 dir_where_cvsadm_lives = xmalloc (strlen (base_dir) + strlen (dir) + 100);
203 if (dir_where_cvsadm_lives == NULL)
209 /* Allocate some space for the temporary string in which we will
210 construct filenames. */
211 tmp = xmalloc (strlen (base_dir) + strlen (dir) + 100);
215 free (dir_where_cvsadm_lives);
220 /* We make several passes through this loop. On the first pass,
221 we simply create the CVSADM directory in the deepest directory.
222 For each subsequent pass, we try to remove the last path
223 element from DIR, create the CVSADM directory in the remaining
224 pathname, and register the subdirectory in the newly created
230 strcpy (dir_where_cvsadm_lives, base_dir);
231 strcat (dir_where_cvsadm_lives, "/");
232 strcat (dir_where_cvsadm_lives, p);
233 dir_to_register = NULL;
238 (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM);
239 if ((CVS_MKDIR (tmp, 0777) < 0) && (errno != EEXIST))
245 /* Create CVSADM_REP. */
246 (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_REP);
249 /* Use Emptydir as the placeholder until the client sends
250 us the real value. This code is similar to checkout.c
251 (emptydir_name), but the code below returns errors
255 empty = xmalloc (strlen (current_parsed_root->directory)
256 + sizeof (CVSROOTADM)
257 + sizeof (CVSNULLREPOS)
265 /* Create the directory name. */
266 (void) sprintf (empty, "%s/%s/%s", current_parsed_root->directory,
267 CVSROOTADM, CVSNULLREPOS);
269 /* Create the directory if it doesn't exist. */
270 if (! isfile (empty))
273 omask = umask (cvsumask);
274 if (CVS_MKDIR (empty, 0777) < 0)
280 (void) umask (omask);
283 f = CVS_FOPEN (tmp, "w");
290 /* Write the directory name to CVSADM_REP. */
291 if (fprintf (f, "%s\n", empty) < 0)
298 if (fclose (f) == EOF)
305 /* Clean up after ourselves. */
309 /* Create CVSADM_ENT. We open in append mode because we
310 don't want to clobber an existing Entries file. */
311 (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_ENT);
312 f = CVS_FOPEN (tmp, "a");
318 if (fclose (f) == EOF)
324 if (dir_to_register != NULL)
326 /* FIXME: Yes, this results in duplicate entries in the
327 Entries.Log file, but it doesn't currently matter. We
328 might need to change this later on to make sure that we
329 only write one entry. */
331 Subdir_Register (NULL, dir_where_cvsadm_lives, dir_to_register);
337 dir_to_register = strrchr (p, '/');
338 if (dir_to_register == NULL)
341 strcpy (dir_where_cvsadm_lives, base_dir);
346 *dir_to_register = '\0';
348 strcpy (dir_where_cvsadm_lives, base_dir);
349 strcat (dir_where_cvsadm_lives, "/");
350 strcat (dir_where_cvsadm_lives, p);
356 free (dir_where_cvsadm_lives);
364 * Make directory DIR, including all intermediate directories if necessary.
365 * Returns 0 for success or errno code.
371 char *q = xmalloc (strlen (dir) + 1);
380 * Skip over leading slash if present. We won't bother to try to
386 while (*p != '/' && *p != '\0')
390 strncpy (q, dir, p - dir);
392 if (q[p - dir - 1] != '/' && CVS_MKDIR (q, 0777) < 0)
394 int saved_errno = errno;
396 if (saved_errno != EEXIST
397 && ((saved_errno != EACCES && saved_errno != EROFS)
400 retval = saved_errno;
408 if (CVS_MKDIR (dir, 0777) < 0)
421 * Print the error response for error code STATUS. The caller is
422 * reponsible for making sure we get back to the command loop without
423 * any further output occuring.
424 * Must be called only in contexts where it is OK to send output.
427 print_error (int status)
432 buf_output0 (buf_to_net, "error ");
433 msg = strerror (status);
436 sprintf (tmpstr, "unknown error %d", status);
439 buf_output0 (buf_to_net, msg);
440 buf_append_char (buf_to_net, '\n');
442 buf_flush (buf_to_net, 0);
447 static int pending_error;
449 * Malloc'd text for pending error. Each line must start with "E ". The
450 * last line should not end with a newline.
452 static char *pending_error_text;
453 static char *pending_warning_text;
455 /* If an error is pending, print it and return 1. If not, return 0.
456 Also prints pending warnings, but this does not affect the return value.
457 Must be called only in contexts where it is OK to send output. */
459 print_pending_error (void)
461 /* Check this case first since it usually means we are out of memory and
462 * the buffer output routines might try and allocate memory.
464 if (!pending_error_text && pending_error)
466 print_error (pending_error);
471 if (pending_warning_text)
473 buf_output0 (buf_to_net, pending_warning_text);
474 buf_append_char (buf_to_net, '\n');
475 buf_flush (buf_to_net, 0);
477 free (pending_warning_text);
478 pending_warning_text = NULL;
481 if (pending_error_text)
483 buf_output0 (buf_to_net, pending_error_text);
484 buf_append_char (buf_to_net, '\n');
486 print_error (pending_error);
488 buf_output0 (buf_to_net, "error \n");
490 buf_flush (buf_to_net, 0);
493 free (pending_error_text);
494 pending_error_text = NULL;
503 /* Is an error pending? */
504 # define error_pending() (pending_error || pending_error_text)
505 # define warning_pending() (pending_warning_text)
507 /* Allocate SIZE bytes for pending_error_text and return nonzero
508 if we could do it. */
510 alloc_pending_internal (char **dest, size_t size)
512 *dest = malloc (size);
515 pending_error = ENOMEM;
523 /* Allocate SIZE bytes for pending_error_text and return nonzero
524 if we could do it. */
526 alloc_pending (size_t size)
528 if (error_pending ())
529 /* Probably alloc_pending callers will have already checked for
530 this case. But we might as well handle it if they don't, I
533 return alloc_pending_internal (&pending_error_text, size);
538 /* Allocate SIZE bytes for pending_error_text and return nonzero
539 if we could do it. */
541 alloc_pending_warning (size_t size)
543 if (warning_pending ())
544 /* Warnings can be lost here. */
546 return alloc_pending_internal (&pending_warning_text, size);
552 supported_response (char *name)
556 for (rs = responses; rs->name != NULL; ++rs)
557 if (strcmp (rs->name, name) == 0)
558 return rs->status == rs_supported;
559 error (1, 0, "internal error: testing support for unknown response?");
567 * Return true if we need to relay write requests to a primary server
568 * and false otherwise.
572 * - primarily handles :ext: method as this seems most likely to be used in
575 * - :fork: method is handled for testing.
577 * - Could handle pserver too, but would have to store the password
578 * the client sent us.
582 * config->PrimaryServer
583 * The parsed setting from CVSROOT/config, if any, or
585 * current_parsed_root The current repository.
588 * true If this server is configured as a secondary server.
594 assert (current_parsed_root);
597 *** The following is done as a series of if/return combinations an an
601 /* If there is no primary server defined in CVSROOT/config, then we can't
604 if (!config || !config->PrimaryServer) return false;
606 /* The directory must not match for all methods. */
607 if (!isSamePath (config->PrimaryServer->directory,
608 current_parsed_root->directory))
611 /* Only the directory is important for fork. */
612 if (config->PrimaryServer->method == fork_method)
615 /* Must be :ext: method, then. This is enforced when CVSROOT/config is
618 assert (config->PrimaryServer->isremote);
620 if (isThisHost (config->PrimaryServer->hostname))
629 serve_valid_responses (char *arg)
635 # ifdef PROXY_SUPPORT
636 /* Process this in the first pass since the data it gathers can be used
637 * prior to a `Root' request.
639 if (reprocessing) return;
640 # endif /* PROXY_SUPPORT */
647 for (rs = responses; rs->name != NULL; ++rs)
649 if (strcmp (rs->name, p) == 0)
652 if (rs->name == NULL)
654 * It is a response we have never heard of (and thus never
655 * will want to use). So don't worry about it.
659 rs->status = rs_supported;
662 for (rs = responses; rs->name != NULL; ++rs)
664 if (rs->status == rs_essential)
666 buf_output0 (buf_to_net, "E response `");
667 buf_output0 (buf_to_net, rs->name);
668 buf_output0 (buf_to_net, "' not supported by client\nerror \n");
670 /* FIXME: This call to buf_flush could conceivably
671 cause deadlock, as noted in server_cleanup. */
672 buf_flush (buf_to_net, 1);
676 else if (rs->status == rs_optional)
677 rs->status = rs_not_supported;
684 * Process IDs of the subprocess, or negative if that subprocess
687 static pid_t command_pid;
690 outbuf_memory_error (struct buffer *buf)
692 static const char msg[] = "E Fatal server error\n\
693 error ENOMEM Virtual memory exhausted.\n";
695 kill (command_pid, SIGTERM);
698 * We have arranged things so that printing this now either will
699 * be valid, or the "E fatal error" line will get glommed onto the
700 * end of an existing "E" or "M" response.
703 /* If this gives an error, not much we could do. syslog() it? */
704 write (STDOUT_FILENO, msg, sizeof (msg) - 1);
705 # ifdef HAVE_SYSLOG_H
706 syslog (LOG_DAEMON | LOG_ERR, "virtual memory exhausted");
707 # endif /* HAVE_SYSLOG_H */
714 input_memory_error (struct buffer *buf)
716 outbuf_memory_error (buf);
721 # ifdef PROXY_SUPPORT
722 /* This function rewinds the net connection using the write proxy log file.
725 * proxy_log The buffer object containing the write proxy log.
731 rewind_buf_from_net (void)
737 /* Free the arguments since we processed some of them in the first pass.
740 /* argument_vector[0] is a dummy argument, we don't mess with
744 for (cp = argument_vector + 1;
745 cp < argument_vector + argument_count;
752 log = log_buffer_rewind (proxy_log);
754 /* Dispose of any read but unused data in the net buffer since it will
755 * already be in the log.
757 buf_free_data (buf_from_net);
758 buf_from_net = ms_buffer_initialize (outbuf_memory_error, log,
762 # endif /* PROXY_SUPPORT */
771 * This request cannot be ignored by a potential secondary since it is used to
772 * determine if we _are_ a secondary.
775 serve_root (char *arg)
779 TRACE (TRACE_FUNCTION, "serve_root (%s)", arg ? arg : "(null)");
781 /* Don't process this twice or when errors are pending. */
783 # ifdef PROXY_SUPPORT
785 # endif /* PROXY_SUPPORT */
788 if (!ISABSOLUTE (arg))
790 if (alloc_pending (80 + strlen (arg)))
791 sprintf (pending_error_text,
792 "E Root %s must be an absolute pathname", arg);
796 /* Sending "Root" twice is invalid.
798 The other way to handle a duplicate Root requests would be as a
799 request to clear out all state and start over as if it was a
800 new connection. Doing this would cause interoperability
801 headaches, so it should be a different request, if there is
802 any reason why such a feature is needed. */
803 if (current_parsed_root != NULL)
805 if (alloc_pending (80 + strlen (arg)))
806 sprintf (pending_error_text,
807 "E Protocol error: Duplicate Root request, for %s", arg);
811 /* Set original_parsed_root here, not because it can be changed in the
812 * client Redirect sense, but so we don't have to switch in code that
813 * runs in both modes to decide which to print.
815 original_parsed_root = current_parsed_root = local_cvsroot (arg);
817 # ifdef AUTH_SERVER_SUPPORT
818 if (Pserver_Repos != NULL)
820 if (strcmp (Pserver_Repos, current_parsed_root->directory) != 0)
822 if (alloc_pending (80 + strlen (Pserver_Repos)
823 + strlen (current_parsed_root->directory)))
824 /* The explicitness is to aid people who are writing clients.
825 I don't see how this information could help an
827 sprintf (pending_error_text, "\
828 E Protocol error: Root says \"%s\" but pserver says \"%s\"",
829 current_parsed_root->directory, Pserver_Repos);
835 if (root_allow_used() && !root_allow_ok(arg))
837 if (alloc_pending (80 + strlen (arg)))
838 sprintf (pending_error_text,
839 "E Bad root %s", arg);
843 /* For pserver, this will already have happened, and the call will do
844 nothing. But for rsh, we need to do it now. */
845 config = get_root_allow_config (current_parsed_root->directory,
848 # ifdef PROXY_SUPPORT
849 /* At this point we have enough information to determine if we are a
850 * secondary server or not.
852 if (proxy_log && !isProxyServer ())
854 /* Else we are not a secondary server. There is no point in
855 * reprocessing since we handle all the requests we can receive
856 * before `Root' as we receive them. But close the logs.
858 log_buffer_closelog (proxy_log);
859 log_buffer_closelog (proxy_log_out);
862 * Don't need this. We assume it when proxy_log == NULL.
864 * proxy_log_out = NULL;
867 # endif /* PROXY_SUPPORT */
869 /* Now set the TMPDIR environment variable. If it was set in the config
870 * file, we now know it.
872 push_env_temp_dir ();
874 /* OK, now figure out where we stash our temporary files. */
878 /* The code which wants to chdir into server_temp_dir is not set
879 * up to deal with it being a relative path. So give an error
882 if (!ISABSOLUTE (get_cvs_tmp_dir ()))
884 if (alloc_pending (80 + strlen (get_cvs_tmp_dir ())))
885 sprintf (pending_error_text,
886 "E Value of %s for TMPDIR is not absolute",
889 /* FIXME: we would like this error to be persistent, that
890 * is, not cleared by print_pending_error. The current client
891 * will exit as soon as it gets an error, but the protocol spec
892 * does not require a client to do so.
900 server_temp_dir = xmalloc (strlen (get_cvs_tmp_dir ()) + 80);
901 if (!server_temp_dir)
903 /* Strictly speaking, we're not supposed to output anything
904 * now. But we're about to exit(), give it a try.
906 printf ("E Fatal server error, aborting.\n\
907 error ENOMEM Virtual memory exhausted.\n");
911 strcpy (server_temp_dir, get_cvs_tmp_dir ());
913 /* Remove a trailing slash from TMPDIR if present. */
914 p = server_temp_dir + strlen (server_temp_dir) - 1;
918 /* I wanted to use cvs-serv/PID, but then you have to worry about
919 * the permissions on the cvs-serv directory being right. So
922 strcat (server_temp_dir, "/cvs-serv");
924 p = server_temp_dir + strlen (server_temp_dir);
925 sprintf (p, "%ld", (long) getpid ());
927 orig_server_temp_dir = server_temp_dir;
929 /* Create the temporary directory, and set the mode to
930 * 700, to discourage random people from tampering with
933 while ((status = mkdir_p (server_temp_dir)) == EEXIST)
935 static const char suffix[] = "abcdefghijklmnopqrstuvwxyz";
937 if (i >= sizeof suffix - 1) break;
938 if (i == 0) p = server_temp_dir + strlen (server_temp_dir);
944 if (alloc_pending (80 + strlen (server_temp_dir)))
945 sprintf (pending_error_text,
946 "E can't create temporary directory %s",
948 pending_error = status;
951 else if (chmod (server_temp_dir, S_IRWXU) < 0)
953 int save_errno = errno;
954 if (alloc_pending (80 + strlen (server_temp_dir)))
955 sprintf (pending_error_text,
956 "E cannot change permissions on temporary directory %s",
958 pending_error = save_errno;
961 else if (CVS_CHDIR (server_temp_dir) < 0)
963 int save_errno = errno;
964 if (alloc_pending (80 + strlen (server_temp_dir)))
965 sprintf (pending_error_text,
966 "E cannot change to temporary directory %s",
968 pending_error = save_errno;
973 /* Now that we have a config, verify our compression level. Since
974 * most clients do not send Gzip-stream requests until after the root
975 * request, wait until the first request following Root to verify that
976 * compression is being used when level 0 is not allowed.
982 if (gzip_level < config->MinCompressionLevel)
984 gzip_level = config->MinCompressionLevel;
988 if (gzip_level > config->MaxCompressionLevel)
990 gzip_level = config->MaxCompressionLevel;
995 && alloc_pending_warning (120 + strlen (program_name)))
996 sprintf (pending_warning_text,
997 "E %s server: Forcing compression level %d (allowed: %d <= z <= %d).",
998 program_name, gzip_level, config->MinCompressionLevel,
999 config->MaxCompressionLevel);
1002 path = xmalloc (strlen (current_parsed_root->directory)
1003 + sizeof (CVSROOTADM)
1007 pending_error = ENOMEM;
1010 (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM);
1011 if (!isaccessible (path, R_OK | X_OK))
1013 int save_errno = errno;
1014 if (alloc_pending (80 + strlen (path)))
1015 sprintf (pending_error_text, "E Cannot access %s", path);
1016 pending_error = save_errno;
1020 setenv (CVSROOT_ENV, current_parsed_root->directory, 1);
1025 static int max_dotdot_limit = 0;
1027 /* Is this pathname OK to recurse into when we are running as the server?
1028 If not, call error() with a fatal error. */
1030 server_pathname_check (char *path)
1032 TRACE (TRACE_FUNCTION, "server_pathname_check (%s)",
1033 path ? path : "(null)");
1035 /* An absolute pathname is almost surely a path on the *client* machine,
1036 and is unlikely to do us any good here. It also is probably capable
1037 of being a security hole in the anonymous readonly case. */
1038 if (ISABSOLUTE (path))
1039 /* Giving an error is actually kind of a cop-out, in the sense
1040 that it would be nice for "cvs co -d /foo/bar/baz" to work.
1041 A quick fix in the server would be requiring Max-dotdot of
1042 at least one if pathnames are absolute, and then putting
1043 /abs/foo/bar/baz in the temp dir beside the /d/d/d stuff.
1044 A cleaner fix in the server might be to decouple the
1045 pathnames we pass back to the client from pathnames in our
1046 temp directory (this would also probably remove the need
1047 for Max-dotdot). A fix in the client would have the client
1048 turn it into "cd /foo/bar; cvs co -d baz" (more or less).
1049 This probably has some problems with pathnames which appear
1052 "absolute pathnames invalid for server (specified `%s')",
1054 if (pathname_levels (path) > max_dotdot_limit)
1056 /* Similar to the ISABSOLUTE case in security implications. */
1057 error (0, 0, "protocol error: `%s' contains more leading ..", path);
1058 error (1, 0, "than the %d which Max-dotdot specified",
1065 /* Is file or directory REPOS an absolute pathname within the
1066 current_parsed_root->directory? If yes, return 0. If no, set pending_error
1069 outside_root (char *repos)
1071 size_t repos_len = strlen (repos);
1072 size_t root_len = strlen (current_parsed_root->directory);
1074 /* ISABSOLUTE (repos) should always be true, but
1075 this is a good security precaution regardless. -DRP
1077 if (!ISABSOLUTE (repos))
1079 if (alloc_pending (repos_len + 80))
1080 sprintf (pending_error_text, "\
1081 E protocol error: %s is not absolute", repos);
1085 if (repos_len < root_len
1086 || strncmp (current_parsed_root->directory, repos, root_len) != 0)
1089 if (alloc_pending (strlen (current_parsed_root->directory)
1092 sprintf (pending_error_text, "\
1093 E protocol error: directory '%s' not within root '%s'",
1094 repos, current_parsed_root->directory);
1097 if (repos_len > root_len)
1099 if (repos[root_len] != '/')
1101 if (pathname_levels (repos + root_len + 1) > 0)
1109 /* Is file or directory FILE outside the current directory (that is, does
1110 it contain '/')? If no, return 0. If yes, set pending_error
1113 outside_dir (char *file)
1115 if (strchr (file, '/') != NULL)
1117 if (alloc_pending (strlen (file)
1119 sprintf (pending_error_text, "\
1120 E protocol error: directory '%s' not within current directory",
1130 * Add as many directories to the temp directory as the client tells us it
1131 * will use "..", so we never try to access something outside the temp
1132 * directory via "..".
1135 serve_max_dotdot (char *arg)
1137 int lim = atoi (arg);
1141 #ifdef PROXY_SUPPORT
1142 if (proxy_log) return;
1143 #endif /* PROXY_SUPPORT */
1145 if (lim < 0 || lim > 10000)
1147 p = xmalloc (strlen (server_temp_dir) + 2 * lim + 10);
1150 pending_error = ENOMEM;
1153 strcpy (p, server_temp_dir);
1154 for (i = 0; i < lim; ++i)
1156 if (server_temp_dir != orig_server_temp_dir)
1157 free (server_temp_dir);
1158 server_temp_dir = p;
1159 max_dotdot_limit = lim;
1164 static char *gDirname;
1165 static char *gupdate_dir;
1168 dirswitch (char *dir, char *repos)
1174 TRACE (TRACE_FUNCTION, "dirswitch (%s, %s)", dir ? dir : "(null)",
1175 repos ? repos : "(null)");
1177 server_write_entries ();
1179 if (error_pending()) return;
1181 /* Check for bad directory name.
1183 FIXME: could/should unify these checks with server_pathname_check
1184 except they need to report errors differently. */
1185 if (ISABSOLUTE (dir))
1187 if (alloc_pending (80 + strlen (dir)))
1188 sprintf ( pending_error_text,
1189 "E absolute pathnames invalid for server (specified `%s')",
1193 if (pathname_levels (dir) > max_dotdot_limit)
1195 if (alloc_pending (80 + strlen (dir)))
1196 sprintf (pending_error_text,
1197 "E protocol error: `%s' has too many ..", dir);
1201 dir_len = strlen (dir);
1203 /* Check for a trailing '/'. This is not ISSLASH because \ in the
1204 protocol is an ordinary character, not a directory separator (of
1205 course, it is perhaps unwise to use it in directory names, but that
1206 is another issue). */
1208 && dir[dir_len - 1] == '/')
1210 if (alloc_pending (80 + dir_len))
1211 sprintf (pending_error_text,
1212 "E protocol error: invalid directory syntax in %s", dir);
1216 if (gDirname != NULL)
1218 if (gupdate_dir != NULL)
1221 if (!strcmp (dir, "."))
1222 gupdate_dir = xstrdup ("");
1224 gupdate_dir = xstrdup (dir);
1226 gDirname = xmalloc (strlen (server_temp_dir) + dir_len + 40);
1227 if (gDirname == NULL)
1229 pending_error = ENOMEM;
1233 strcpy (gDirname, server_temp_dir);
1234 strcat (gDirname, "/");
1235 strcat (gDirname, dir);
1237 status = mkdir_p (gDirname);
1239 && status != EEXIST)
1241 if (alloc_pending (80 + strlen (gDirname)))
1242 sprintf (pending_error_text, "E cannot mkdir %s", gDirname);
1243 pending_error = status;
1247 /* We need to create adm directories in all path elements because
1248 we want the server to descend them, even if the client hasn't
1249 sent the appropriate "Argument xxx" command to match the
1250 already-sent "Directory xxx" command. See recurse.c
1251 (start_recursion) for a big discussion of this. */
1253 status = create_adm_p (server_temp_dir, dir);
1256 if (alloc_pending (80 + strlen (gDirname)))
1257 sprintf (pending_error_text, "E cannot create_adm_p %s", gDirname);
1258 pending_error = status;
1262 if ( CVS_CHDIR (gDirname) < 0)
1264 int save_errno = errno;
1265 if (alloc_pending (80 + strlen (gDirname)))
1266 sprintf (pending_error_text, "E cannot change to %s", gDirname);
1267 pending_error = save_errno;
1271 * This is pretty much like calling Create_Admin, but Create_Admin doesn't
1272 * report errors in the right way for us.
1274 if ((CVS_MKDIR (CVSADM, 0777) < 0) && (errno != EEXIST))
1276 int save_errno = errno;
1277 if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM)))
1278 sprintf (pending_error_text,
1279 "E cannot mkdir %s/%s", gDirname, CVSADM);
1280 pending_error = save_errno;
1284 /* The following will overwrite the contents of CVSADM_REP. This
1285 is the correct behavior -- mkdir_p may have written a
1286 placeholder value to this file and we need to insert the
1289 f = CVS_FOPEN (CVSADM_REP, "w");
1292 int save_errno = errno;
1293 if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1294 sprintf (pending_error_text,
1295 "E cannot open %s/%s", gDirname, CVSADM_REP);
1296 pending_error = save_errno;
1299 if (fprintf (f, "%s", repos) < 0)
1301 int save_errno = errno;
1302 if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1303 sprintf (pending_error_text,
1304 "E error writing %s/%s", gDirname, CVSADM_REP);
1305 pending_error = save_errno;
1309 /* Non-remote CVS handles a module representing the entire tree
1310 (e.g., an entry like ``world -a .'') by putting /. at the end
1311 of the Repository file, so we do the same. */
1312 if (strcmp (dir, ".") == 0
1313 && current_parsed_root != NULL
1314 && current_parsed_root->directory != NULL
1315 && strcmp (current_parsed_root->directory, repos) == 0)
1317 if (fprintf (f, "/.") < 0)
1319 int save_errno = errno;
1320 if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1321 sprintf (pending_error_text,
1322 "E error writing %s/%s", gDirname, CVSADM_REP);
1323 pending_error = save_errno;
1328 if (fprintf (f, "\n") < 0)
1330 int save_errno = errno;
1331 if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1332 sprintf (pending_error_text,
1333 "E error writing %s/%s", gDirname, CVSADM_REP);
1334 pending_error = save_errno;
1338 if (fclose (f) == EOF)
1340 int save_errno = errno;
1341 if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1342 sprintf (pending_error_text,
1343 "E error closing %s/%s", gDirname, CVSADM_REP);
1344 pending_error = save_errno;
1347 /* We open in append mode because we don't want to clobber an
1348 existing Entries file. */
1349 f = CVS_FOPEN (CVSADM_ENT, "a");
1352 int save_errno = errno;
1353 if (alloc_pending (80 + strlen (CVSADM_ENT)))
1354 sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
1355 pending_error = save_errno;
1358 if (fclose (f) == EOF)
1360 int save_errno = errno;
1361 if (alloc_pending (80 + strlen (CVSADM_ENT)))
1362 sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
1363 pending_error = save_errno;
1371 serve_repository (char *arg)
1373 # ifdef PROXY_SUPPORT
1374 assert (!proxy_log);
1375 # endif /* PROXY_SUPPORT */
1377 if (alloc_pending (80))
1378 strcpy (pending_error_text,
1379 "E Repository request is obsolete; aborted");
1386 serve_directory (char *arg)
1391 TRACE (TRACE_FUNCTION, "serve_directory (%s)", arg ? arg : "(null)");
1394 /* The data needs to be read into the secondary log regardless, but
1395 * processing of anything other than errors is skipped until later.
1397 status = buf_read_line (buf_from_net, &repos, NULL);
1400 if (!ISABSOLUTE (repos))
1404 * FIXME: This is kinda hacky - we should probably only ever store
1405 * and pass SHORT_REPOS (perhaps with the occassional exception
1406 * for optimizations, but many, many functions end up
1407 * deconstructing REPOS to gain SHORT_REPOS anyhow) - the
1408 * CVSROOT portion of REPOS is redundant with
1409 * current_parsed_root->directory - but since this is the way
1410 * things have always been done, changing this will likely involve
1415 short_repos = repos;
1416 repos = Xasprintf ("%s/%s",
1417 current_parsed_root->directory, short_repos);
1421 repos = xstrdup (primary_root_translate (repos));
1424 # ifdef PROXY_SUPPORT
1426 # endif /* PROXY_SUPPORT */
1427 !outside_root (repos))
1428 dirswitch (arg, repos);
1431 else if (status == -2)
1433 pending_error = ENOMEM;
1435 else if (status != 0)
1437 pending_error_text = xmalloc (80 + strlen (arg));
1438 if (pending_error_text == NULL)
1440 pending_error = ENOMEM;
1442 else if (status == -1)
1444 sprintf (pending_error_text,
1445 "E end of file reading mode for %s", arg);
1449 sprintf (pending_error_text,
1450 "E error reading mode for %s", arg);
1451 pending_error = status;
1459 serve_static_directory (char *arg)
1463 if (error_pending ()
1464 # ifdef PROXY_SUPPORT
1466 # endif /* PROXY_SUPPORT */
1469 f = CVS_FOPEN (CVSADM_ENTSTAT, "w+");
1472 int save_errno = errno;
1473 if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
1474 sprintf (pending_error_text, "E cannot open %s", CVSADM_ENTSTAT);
1475 pending_error = save_errno;
1478 if (fclose (f) == EOF)
1480 int save_errno = errno;
1481 if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
1482 sprintf (pending_error_text, "E cannot close %s", CVSADM_ENTSTAT);
1483 pending_error = save_errno;
1491 serve_sticky (char *arg)
1495 if (error_pending ()
1496 # ifdef PROXY_SUPPORT
1498 # endif /* PROXY_SUPPORT */
1501 f = CVS_FOPEN (CVSADM_TAG, "w+");
1504 int save_errno = errno;
1505 if (alloc_pending (80 + strlen (CVSADM_TAG)))
1506 sprintf (pending_error_text, "E cannot open %s", CVSADM_TAG);
1507 pending_error = save_errno;
1510 if (fprintf (f, "%s\n", arg) < 0)
1512 int save_errno = errno;
1513 if (alloc_pending (80 + strlen (CVSADM_TAG)))
1514 sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG);
1515 pending_error = save_errno;
1518 if (fclose (f) == EOF)
1520 int save_errno = errno;
1521 if (alloc_pending (80 + strlen (CVSADM_TAG)))
1522 sprintf (pending_error_text, "E cannot close %s", CVSADM_TAG);
1523 pending_error = save_errno;
1531 * Read SIZE bytes from buf_from_net, write them to FILE.
1533 * Currently this isn't really used for receiving parts of a file --
1534 * the file is still sent over in one chunk. But if/when we get
1535 * spiffy in-process gzip support working, perhaps the compressed
1536 * pieces could be sent over as they're ready, if the network is fast
1537 * enough. Or something.
1540 receive_partial_file (size_t size, int file)
1548 status = buf_read_data (buf_from_net, size, &data, &nread);
1552 pending_error = ENOMEM;
1555 pending_error_text = xmalloc (80);
1556 if (pending_error_text == NULL)
1557 pending_error = ENOMEM;
1558 else if (status == -1)
1560 sprintf (pending_error_text,
1561 "E premature end of file from client");
1566 sprintf (pending_error_text,
1567 "E error reading from client");
1568 pending_error = status;
1580 nwrote = write (file, data, nread);
1583 int save_errno = errno;
1584 if (alloc_pending (40))
1585 strcpy (pending_error_text, "E unable to write");
1586 pending_error = save_errno;
1588 /* Read and discard the file data. */
1595 status = buf_read_data (buf_from_net, size, &data, &nread);
1611 /* Receive SIZE bytes, write to filename FILE. */
1613 receive_file (size_t size, char *file, int gzipped)
1618 /* Write the file. */
1619 fd = CVS_OPEN (arg, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1622 int save_errno = errno;
1623 if (alloc_pending (40 + strlen (arg)))
1624 sprintf (pending_error_text, "E cannot open %s", arg);
1625 pending_error = save_errno;
1631 /* Using gunzip_and_write isn't really a high-performance
1632 approach, because it keeps the whole thing in memory
1633 (contiguous memory, worse yet). But it seems easier to
1634 code than the alternative (and less vulnerable to subtle
1635 bugs). Given that this feature is mainly for
1636 compatibility, that is the better tradeoff. */
1638 size_t toread = size;
1642 filebuf = xmalloc (size);
1644 /* If NULL, we still want to read the data and discard it. */
1652 status = buf_read_data (buf_from_net, toread, &data, &nread);
1656 pending_error = ENOMEM;
1659 pending_error_text = xmalloc (80);
1660 if (pending_error_text == NULL)
1661 pending_error = ENOMEM;
1662 else if (status == -1)
1664 sprintf (pending_error_text,
1665 "E premature end of file from client");
1670 sprintf (pending_error_text,
1671 "E error reading from client");
1672 pending_error = status;
1680 if (filebuf != NULL)
1682 memcpy (p, data, nread);
1686 if (filebuf == NULL)
1688 pending_error = ENOMEM;
1692 if (gunzip_and_write (fd, file, (unsigned char *) filebuf, size))
1694 if (alloc_pending (80))
1695 sprintf (pending_error_text,
1696 "E aborting due to compression error");
1701 receive_partial_file (size, fd);
1703 if (pending_error_text)
1705 char *p = xrealloc (pending_error_text,
1706 strlen (pending_error_text) + strlen (arg) + 30);
1709 pending_error_text = p;
1710 sprintf (p + strlen (p), ", file %s", arg);
1712 /* else original string is supposed to be unchanged */
1716 if (close (fd) < 0 && !error_pending ())
1718 int save_errno = errno;
1719 if (alloc_pending (40 + strlen (arg)))
1720 sprintf (pending_error_text, "E cannot close %s", arg);
1721 pending_error = save_errno;
1728 /* Kopt for the next file sent in Modified or Is-modified. */
1731 /* Timestamp (Checkin-time) for next file sent in Modified or
1733 static int checkin_time_valid;
1734 static time_t checkin_time;
1739 * Used to keep track of Entry requests.
1742 struct an_entry *next;
1746 static struct an_entry *entries;
1749 serve_is_modified (char *arg)
1755 /* Have we found this file in "entries" yet. */
1758 if (error_pending ()
1759 # ifdef PROXY_SUPPORT
1761 # endif /* PROXY_SUPPORT */
1764 if (outside_dir (arg))
1767 /* Rewrite entries file to have `M' in timestamp field. */
1769 for (p = entries; p != NULL; p = p->next)
1771 name = p->entry + 1;
1772 cp = strchr (name, '/');
1774 && strlen (arg) == cp - name
1775 && strncmp (arg, name, cp - name) == 0)
1777 if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
1779 /* We didn't find the record separator or it is followed by
1780 * the end of the string, so just exit.
1782 if (alloc_pending (80))
1783 sprintf (pending_error_text,
1784 "E Malformed Entry encountered.");
1787 /* If the time field is not currently empty, then one of
1788 * serve_modified, serve_is_modified, & serve_unchanged were
1789 * already called for this file. We would like to ignore the
1790 * reinvocation silently or, better yet, exit with an error
1791 * message, but we just avoid the copy-forward and overwrite the
1792 * value from the last invocation instead. See the comment below
1795 if (*timefield == '/')
1797 /* Copy forward one character. Space was allocated for this
1798 * already in serve_entry(). */
1799 cp = timefield + strlen (timefield);
1801 while (cp > timefield)
1807 /* *timefield == '/'; */
1809 /* If *TIMEFIELD wasn't '/' and wasn't '+', we assume that it was
1810 * because of multiple calls to Is-modified & Unchanged by the
1811 * client and just overwrite the value from the last call.
1812 * Technically, we should probably either ignore calls after the
1813 * first or send the client an error, since the client/server
1814 * protocol specification specifies that only one call to either
1815 * Is-Modified or Unchanged is allowed, but broken versions of
1816 * CVSNT (at least 2.0.34 - 2.0.41, reported fixed in 2.0.41a) and
1817 * the WinCVS & TortoiseCVS clients which depend on those broken
1818 * versions of CVSNT (WinCVS 1.3 & at least one TortoiseCVS
1819 * release) rely on this behavior.
1821 if (*timefield != '+')
1826 if (alloc_pending (strlen (name) + 80))
1827 sprintf (pending_error_text,
1828 "E protocol error: both Kopt and Entry for %s",
1840 /* We got Is-modified but no Entry. Add a dummy entry.
1841 The "D" timestamp is what makes it a dummy. */
1842 p = xmalloc (sizeof (struct an_entry));
1845 pending_error = ENOMEM;
1848 p->entry = xmalloc (strlen (arg) + 80);
1849 if (p->entry == NULL)
1851 pending_error = ENOMEM;
1855 strcpy (p->entry, "/");
1856 strcat (p->entry, arg);
1857 strcat (p->entry, "//D/");
1860 strcat (p->entry, kopt);
1864 strcat (p->entry, "/");
1873 serve_modified (char *arg)
1884 * This used to return immediately if error_pending () was true.
1885 * However, that fails, because it causes each line of the file to
1886 * be echoed back to the client as an unrecognized command. The
1887 * client isn't reading from the socket, so eventually both
1888 * processes block trying to write to the other. Now, we try to
1889 * read the file if we can.
1892 status = buf_read_line (buf_from_net, &mode_text, NULL);
1896 pending_error = ENOMEM;
1899 pending_error_text = xmalloc (80 + strlen (arg));
1900 if (pending_error_text == NULL)
1901 pending_error = ENOMEM;
1905 sprintf (pending_error_text,
1906 "E end of file reading mode for %s", arg);
1909 sprintf (pending_error_text,
1910 "E error reading mode for %s", arg);
1911 pending_error = status;
1918 status = buf_read_line (buf_from_net, &size_text, NULL);
1922 pending_error = ENOMEM;
1925 pending_error_text = xmalloc (80 + strlen (arg));
1926 if (pending_error_text == NULL)
1927 pending_error = ENOMEM;
1931 sprintf (pending_error_text,
1932 "E end of file reading size for %s", arg);
1935 sprintf (pending_error_text,
1936 "E error reading size for %s", arg);
1937 pending_error = status;
1944 if (size_text[0] == 'z')
1947 read_size = atoi (size_text + 1);
1950 read_size = atoi (size_text);
1953 if (read_size < 0 && alloc_pending (80))
1955 sprintf (pending_error_text,
1956 "E client sent invalid (negative) file size");
1962 if (error_pending ())
1964 /* Now that we know the size, read and discard the file data. */
1971 status = buf_read_data (buf_from_net, size, &data, &nread);
1981 # ifdef PROXY_SUPPORT
1983 # endif /* PROXY_SUPPORT */
1991 # ifdef PROXY_SUPPORT
1992 proxy_log ? DEVNULL :
1993 # endif /* PROXY_SUPPORT */
1996 if (error_pending ())
2002 # ifdef PROXY_SUPPORT
2003 /* We've read all the data that needed to be read if we're still logging
2004 * for a secondary. Return.
2006 if (proxy_log) return;
2007 # endif /* PROXY_SUPPORT */
2009 if (checkin_time_valid)
2013 memset (&t, 0, sizeof (t));
2014 t.modtime = t.actime = checkin_time;
2015 if (utime (arg, &t) < 0)
2017 int save_errno = errno;
2018 if (alloc_pending (80 + strlen (arg)))
2019 sprintf (pending_error_text, "E cannot utime %s", arg);
2020 pending_error = save_errno;
2024 checkin_time_valid = 0;
2028 int status = change_mode (arg, mode_text, 0);
2032 if (alloc_pending (40 + strlen (arg)))
2033 sprintf (pending_error_text,
2034 "E cannot change mode for %s", arg);
2035 pending_error = status;
2040 /* Make sure that the Entries indicate the right kopt. We probably
2041 could do this even in the non-kopt case and, I think, save a stat()
2042 call in time_stamp_server. But for conservatism I'm leaving the
2043 non-kopt case alone. */
2045 serve_is_modified (arg);
2051 serve_enable_unchanged (char *arg)
2053 # ifdef PROXY_SUPPORT
2054 /* Might as well skip this since this function does nothing anyhow. If
2055 * it did do anything and could generate errors, then the line below would
2056 * be necessary since this can be processed before a `Root' request.
2058 * if (reprocessing) return;
2060 # endif /* PROXY_SUPPORT */
2066 serve_unchanged (char *arg)
2073 if (error_pending ()
2074 # ifdef PROXY_SUPPORT
2076 # endif /* PROXY_SUPPORT */
2079 if (outside_dir (arg))
2082 /* Rewrite entries file to have `=' in timestamp field. */
2083 for (p = entries; p != NULL; p = p->next)
2085 name = p->entry + 1;
2086 cp = strchr (name, '/');
2088 && strlen (arg) == cp - name
2089 && strncmp (arg, name, cp - name) == 0)
2091 if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
2093 /* We didn't find the record separator or it is followed by
2094 * the end of the string, so just exit.
2096 if (alloc_pending (80))
2097 sprintf (pending_error_text,
2098 "E Malformed Entry encountered.");
2101 /* If the time field is not currently empty, then one of
2102 * serve_modified, serve_is_modified, & serve_unchanged were
2103 * already called for this file. We would like to ignore the
2104 * reinvocation silently or, better yet, exit with an error
2105 * message, but we just avoid the copy-forward and overwrite the
2106 * value from the last invocation instead. See the comment below
2109 if (*timefield == '/')
2111 /* Copy forward one character. Space was allocated for this
2112 * already in serve_entry(). */
2113 cp = timefield + strlen (timefield);
2115 while (cp > timefield)
2121 /* *timefield == '/'; */
2123 if (*timefield != '+')
2125 /* '+' is a conflict marker and we don't want to mess with it
2126 * until Version_TS catches it.
2128 if (timefield[1] != '/')
2130 /* Obliterate anything else in TIMEFIELD. This is again to
2131 * support the broken CVSNT clients mentioned below, in
2132 * conjunction with strict timestamp string boundry
2133 * checking in time_stamp_server() from vers_ts.c &
2134 * file_has_conflict() from subr.c, since the broken
2135 * clients used to send malformed timestamp fields in the
2136 * Entry request that they then depended on the subsequent
2137 * Unchanged request to overwrite.
2139 char *d = timefield + 1;
2140 if ((cp = strchr (d, '/')))
2149 /* If *TIMEFIELD wasn't '/', we assume that it was because of
2150 * multiple calls to Is-modified & Unchanged by the client and
2151 * just overwrite the value from the last call. Technically,
2152 * we should probably either ignore calls after the first or
2153 * send the client an error, since the client/server protocol
2154 * specification specifies that only one call to either
2155 * Is-Modified or Unchanged is allowed, but broken versions of
2156 * CVSNT (at least 2.0.34 - 2.0.41, reported fixed in 2.0.41a)
2157 * and the WinCVS & TortoiseCVS clients which depend on those
2158 * broken versions of CVSNT (WinCVS 1.3 & at least one
2159 * TortoiseCVS release) rely on this behavior.
2171 serve_entry (char *arg)
2178 # ifdef PROXY_SUPPORT
2180 # endif /* PROXY_SUPPORT */
2183 /* Verify that the entry is well-formed. This can avoid problems later.
2184 * At the moment we only check that the Entry contains five slashes in
2185 * approximately the correct locations since some of the code makes
2186 * assumptions about this.
2189 if (*cp == 'D') cp++;
2192 if (!cp || *cp != '/')
2194 if (alloc_pending (80))
2195 sprintf (pending_error_text,
2196 "E protocol error: Malformed Entry");
2199 cp = strchr (cp + 1, '/');
2202 p = xmalloc (sizeof (struct an_entry));
2205 pending_error = ENOMEM;
2208 /* Leave space for serve_unchanged to write '=' if it wants. */
2209 cp = xmalloc (strlen (arg) + 2);
2213 pending_error = ENOMEM;
2225 serve_kopt (char *arg)
2227 if (error_pending ()
2228 # ifdef PROXY_SUPPORT
2230 # endif /* PROXY_SUPPORT */
2236 if (alloc_pending (80 + strlen (arg)))
2237 sprintf (pending_error_text,
2238 "E protocol error: duplicate Kopt request: %s", arg);
2242 /* Do some sanity checks. In particular, that it is not too long.
2243 This lets the rest of the code not worry so much about buffer
2244 overrun attacks. Probably should call RCS_check_kflag here,
2245 but that would mean changing RCS_check_kflag to handle errors
2246 other than via exit(), fprintf(), and such. */
2247 if (strlen (arg) > 10)
2249 if (alloc_pending (80 + strlen (arg)))
2250 sprintf (pending_error_text,
2251 "E protocol error: invalid Kopt request: %s", arg);
2255 kopt = xmalloc (strlen (arg) + 1);
2258 pending_error = ENOMEM;
2267 serve_checkin_time (char *arg)
2271 if (error_pending ()
2272 # ifdef PROXY_SUPPORT
2274 # endif /* PROXY_SUPPORT */
2278 if (checkin_time_valid)
2280 if (alloc_pending (80 + strlen (arg)))
2281 sprintf (pending_error_text,
2282 "E protocol error: duplicate Checkin-time request: %s",
2287 if (!get_date (&t, arg, NULL))
2289 if (alloc_pending (80 + strlen (arg)))
2290 sprintf (pending_error_text, "E cannot parse date %s", arg);
2294 /* Truncate any nanoseconds returned by get_date(). */
2295 checkin_time = t.tv_sec;
2296 checkin_time_valid = 1;
2302 server_write_entries (void)
2308 if (entries == NULL)
2312 /* Note that we free all the entries regardless of errors. */
2313 if (!error_pending ())
2315 /* We open in append mode because we don't want to clobber an
2316 existing Entries file. If we are checking out a module
2317 which explicitly lists more than one file in a particular
2318 directory, then we will wind up calling
2319 server_write_entries for each such file. */
2320 f = CVS_FOPEN (CVSADM_ENT, "a");
2323 int save_errno = errno;
2324 if (alloc_pending (80 + strlen (CVSADM_ENT)))
2325 sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
2326 pending_error = save_errno;
2329 for (p = entries; p != NULL;)
2331 if (!error_pending ())
2333 if (fprintf (f, "%s\n", p->entry) < 0)
2335 int save_errno = errno;
2336 if (alloc_pending (80 + strlen(CVSADM_ENT)))
2337 sprintf (pending_error_text,
2338 "E cannot write to %s", CVSADM_ENT);
2339 pending_error = save_errno;
2348 if (f != NULL && fclose (f) == EOF && !error_pending ())
2350 int save_errno = errno;
2351 if (alloc_pending (80 + strlen (CVSADM_ENT)))
2352 sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
2353 pending_error = save_errno;
2359 # ifdef PROXY_SUPPORT
2361 * callback proc to run a script when admin finishes.
2364 prepost_proxy_proc (const char *repository, const char *filter, void *closure)
2367 bool *pre = closure;
2369 /* %c = cvs_cmd_name
2374 TRACE (TRACE_FUNCTION, "prepost_proxy_proc (%s, %s, %s)", repository,
2375 filter, *pre ? "pre" : "post");
2378 * Cast any NULL arguments as appropriate pointers as this is an
2379 * stdarg function and we need to be certain the caller gets what
2382 cmdline = format_cmdline (
2383 # ifdef SUPPORT_OLD_INFO_FMT_STRINGS
2385 # endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
2387 "c", "s", cvs_cmd_name,
2388 "I", "s", global_session_id,
2389 "R", "s", referrer ? referrer->original : "NONE",
2391 "r", "s", current_parsed_root->directory,
2392 "P", "s", config->PrimaryServer->original,
2395 if (!cmdline || !strlen (cmdline))
2397 if (cmdline) free (cmdline);
2399 error (0, 0, "preadmin proc resolved to the empty string!");
2401 error (0, 0, "postadmin proc resolved to the empty string!");
2405 run_setup (cmdline);
2409 /* FIXME - read the comment in verifymsg_proc() about why we use abs()
2410 * below() and shouldn't.
2412 return abs (run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
2413 RUN_NORMAL | RUN_SIGIGNORE));
2418 /* Become a secondary write proxy to a master server.
2420 * This function opens the connection to the primary, dumps the secondary log
2421 * to the primary, then reads data from any available connection and writes it
2424 * buf_from_net -> buf_to_primary
2425 * buf_from_primary -> buf_to_net
2427 * When all "from" connections have sent EOF and all data has been sent to
2428 * "to" connections, this function closes the "to" pipes and returns.
2433 struct buffer *buf_to_primary;
2434 struct buffer *buf_from_primary;
2436 /* Close the client log and open it for read. */
2437 struct buffer *buf_clientlog = log_buffer_rewind (proxy_log_out);
2438 int status, to_primary_fd, from_primary_fd, to_net_fd, from_net_fd;
2440 /* Call presecondary script. */
2444 size_t thispass, got;
2448 Parse_Info (CVSROOTADM_PREPROXY, current_parsed_root->directory,
2449 prepost_proxy_proc, PIOPT_ALL, &pre);
2451 /* Open connection to primary server. */
2452 open_connection_to_server (config->PrimaryServer, &buf_to_primary,
2454 setup_logfiles ("CVS_SECONDARY_LOG", &buf_to_primary, &buf_from_primary);
2455 if ((status = set_nonblock (buf_from_primary)))
2456 error (1, status, "failed to set nonblocking io from primary");
2457 if ((status = set_nonblock (buf_from_net)))
2458 error (1, status, "failed to set nonblocking io from client");
2459 if ((status = set_nonblock (buf_to_primary)))
2460 error (1, status, "failed to set nonblocking io to primary");
2461 if ((status = set_nonblock (buf_to_net)))
2462 error (1, status, "failed to set nonblocking io to client");
2464 to_primary_fd = buf_get_fd (buf_to_primary);
2465 from_primary_fd = buf_get_fd (buf_from_primary);
2466 to_net_fd = buf_get_fd (buf_to_net);
2467 assert (to_primary_fd >= 0 && from_primary_fd >= 0 && to_net_fd >= 0);
2469 /* Close the client log and open it for read. */
2470 rewind_buf_from_net ();
2472 while (from_primary_fd >= 0 || to_primary_fd >= 0)
2474 fd_set readfds, writefds;
2475 int status, numfds = -1;
2476 struct timeval *timeout_ptr;
2477 struct timeval timeout;
2481 FD_ZERO (&writefds);
2483 /* The fd for a multi-source buffer can change with any read. */
2484 from_net_fd = buf_from_net ? buf_get_fd (buf_from_net) : -1;
2486 if ((buf_from_net && !buf_empty_p (buf_from_net))
2487 || (buf_from_primary && !buf_empty_p (buf_from_primary)))
2489 /* There is data pending so don't block if we don't find any new
2493 timeout.tv_usec = 0;
2494 timeout_ptr = &timeout;
2497 /* block indefinately */
2500 /* Set writefds if data is pending. */
2501 if (to_net_fd >= 0 && !buf_empty_p (buf_to_net))
2503 FD_SET (to_net_fd, &writefds);
2504 numfds = MAX (numfds, to_net_fd);
2506 if (to_primary_fd >= 0 && !buf_empty_p (buf_to_primary))
2508 FD_SET (to_primary_fd, &writefds);
2509 numfds = MAX (numfds, to_primary_fd);
2512 /* Set readfds if descriptors are still open. */
2513 if (from_net_fd >= 0)
2515 FD_SET (from_net_fd, &readfds);
2516 numfds = MAX (numfds, from_net_fd);
2518 if (from_primary_fd >= 0)
2520 FD_SET (from_primary_fd, &readfds);
2521 numfds = MAX (numfds, from_primary_fd);
2524 /* NUMFDS needs to be the highest descriptor + 1 according to the
2530 /* This used to select on exceptions too, but as far
2531 as I know there was never any reason to do that and
2532 SCO doesn't let you select on exceptions on pipes. */
2533 numfds = select (numfds, &readfds, &writefds,
2535 if (numfds < 0 && errno != EINTR)
2537 /* Sending an error to the client, possibly in the middle of a
2538 * separate protocol message, will likely not mean much to the
2539 * client, but it's better than nothing, I guess.
2541 buf_output0 (buf_to_net, "E select failed\n");
2542 print_error (errno);
2543 exit (EXIT_FAILURE);
2545 } while (numfds < 0);
2550 FD_ZERO (&writefds);
2553 if (to_net_fd >= 0 && FD_ISSET (to_net_fd, &writefds))
2555 /* What should we do with errors? syslog() them? */
2556 buf_send_output (buf_to_net);
2557 buf_flush (buf_to_net, false);
2561 if (from_net_fd >= 0 && (FD_ISSET (from_net_fd, &readfds)))
2562 status = buf_input_data (buf_from_net, NULL);
2564 if (buf_from_net && !buf_empty_p (buf_from_net))
2567 buf_append_buffer (buf_to_primary, buf_from_net);
2569 /* (Sys?)log this? */;
2573 if (status == -1 /* EOF */)
2576 /* Need only to shut this down and set to NULL, really, in
2577 * crit sec, to ensure no double-dispose and to make sure
2578 * network pipes are closed as properly as possible, but I
2579 * don't see much optimization potential in saving values and
2580 * postponing the free.
2582 buf_shutdown (buf_from_net);
2583 buf_free (buf_from_net);
2584 buf_from_net = NULL;
2585 /* So buf_to_primary will be closed at the end of this loop. */
2589 else if (status > 0 /* ERRNO */)
2591 buf_output0 (buf_to_net,
2592 "E buf_input_data failed reading from client\n");
2593 print_error (status);
2594 exit (EXIT_FAILURE);
2597 if (to_primary_fd >= 0 && FD_ISSET (to_primary_fd, &writefds))
2599 /* What should we do with errors? syslog() them? */
2600 buf_send_output (buf_to_primary);
2601 buf_flush (buf_to_primary, false);
2605 if (from_primary_fd >= 0 && FD_ISSET (from_primary_fd, &readfds))
2606 status = buf_input_data (buf_from_primary, &toread);
2608 /* Avoid resending data from the server which we already sent to the
2609 * client. Otherwise clients get really confused.
2612 && buf_from_primary && !buf_empty_p (buf_from_primary))
2614 /* Dispose of data we already sent to the client. */
2615 while (buf_clientlog && toread > 0)
2617 s = buf_read_data (buf_clientlog, toread, &data, &got);
2619 error (1, ENOMEM, "Failed to read data.");
2622 buf_shutdown (buf_clientlog);
2623 buf_clientlog = NULL;
2626 error (1, s, "Error reading writeproxy log.");
2630 while (thispass > 0)
2632 /* No need to check for errors here since we know we
2633 * won't read more than buf_input read into
2634 * BUF_FROM_PRIMARY (see how TOREAD is set above).
2636 buf_read_data (buf_from_primary, thispass, &newdata,
2638 /* Verify that we are throwing away what we think we
2641 * It is valid to assume that the secondary and primary
2642 * are closely enough in sync that this portion of the
2643 * communication will be in sync beacuse if they were
2644 * not, then the secondary might provide a
2645 * valid-request string to the client which contained a
2646 * request that the primary didn't support. If the
2647 * client later used the request, the primary server
2648 * would exit anyhow.
2651 * An alternative approach might be to make sure that
2652 * the secondary provides the same string as the
2653 * primary regardless, for purposes like pointing a
2654 * secondary at an unwitting primary, in which case it
2655 * might be useful to have some way to override the
2656 * valid-requests string on a secondary, but it seems
2657 * much easier to simply sync the versions, at the
2660 if (memcmp (data, newdata, got))
2661 error (1, 0, "Secondary out of sync with primary!");
2670 if (buf_from_primary && !buf_empty_p (buf_from_primary))
2673 buf_append_buffer (buf_to_net, buf_from_primary);
2675 /* (Sys?)log this? */;
2679 if (status == -1 /* EOF */)
2681 buf_shutdown (buf_from_primary);
2682 buf_from_primary = NULL;
2683 from_primary_fd = -1;
2685 else if (status > 0 /* ERRNO */)
2687 buf_output0 (buf_to_net,
2688 "E buf_input_data failed reading from primary\n");
2689 print_error (status);
2690 exit (EXIT_FAILURE);
2693 /* If our "source pipe" is closed and all data has been sent, avoid
2694 * selecting it for writability, but don't actually close the buffer in
2695 * case other routines want to use it later. The buffer will be closed
2696 * in server_cleanup ().
2698 if (from_primary_fd < 0
2699 && buf_to_net && buf_empty_p (buf_to_net))
2703 && (/* Assume that there is no further reason to keep the buffer to
2704 * the primary open if we can no longer read its responses.
2706 (from_primary_fd < 0 && buf_to_primary)
2707 /* Also close buf_to_primary when it becomes impossible to find
2708 * more data to send to it. We don't close buf_from_primary
2709 * yet since there may be data pending or the primary may react
2710 * to the EOF on its input pipe.
2712 || (from_net_fd < 0 && buf_empty_p (buf_to_primary))))
2714 buf_shutdown (buf_to_primary);
2715 buf_free (buf_to_primary);
2716 buf_to_primary = NULL;
2718 /* Setting the fd < 0 with from_primary_fd already < 0 will cause
2719 * an escape from this while loop.
2725 /* Call postsecondary script. */
2727 Parse_Info (CVSROOTADM_POSTPROXY, current_parsed_root->directory,
2728 prepost_proxy_proc, PIOPT_ALL, &pre);
2730 # endif /* PROXY_SUPPORT */
2734 struct notify_note {
2735 /* Directory in which this notification happens. xmalloc'd*/
2744 /* The following three all in one xmalloc'd block, pointed to by TYPE.
2745 Each '\0' terminated. */
2752 struct notify_note *next;
2755 static struct notify_note *notify_list;
2756 /* Used while building list, to point to the last node that already exists. */
2757 static struct notify_note *last_node;
2760 serve_notify (char *arg)
2762 struct notify_note *new = NULL;
2766 if (error_pending ()) return;
2768 if (isProxyServer())
2770 # ifdef PROXY_SUPPORT
2773 # endif /* PROXY_SUPPORT */
2774 if (alloc_pending (160) + strlen (program_name))
2775 sprintf (pending_error_text,
2776 "E This CVS server does not support disconnected `%s edit'. For now, remove all `%s' files in your workspace and try your command again.",
2777 program_name, CVSADM_NOTIFY);
2779 # ifdef PROXY_SUPPORT
2783 /* This is effectively a write command, so run it on the primary. */
2785 exit (EXIT_SUCCESS);
2787 # endif /* PROXY_SUPPORT */
2790 if (outside_dir (arg))
2793 if (gDirname == NULL)
2796 new = xmalloc (sizeof (struct notify_note));
2799 pending_error = ENOMEM;
2802 new->dir = xmalloc (strlen (gDirname) + 1);
2803 new->update_dir = xmalloc (strlen (gupdate_dir) + 1);
2804 new->filename = xmalloc (strlen (arg) + 1);
2805 if (new->dir == NULL || new->update_dir == NULL || new->filename == NULL)
2807 pending_error = ENOMEM;
2808 if (new->dir != NULL)
2813 strcpy (new->dir, gDirname);
2814 strcpy (new->update_dir, gupdate_dir);
2815 strcpy (new->filename, arg);
2817 status = buf_read_line (buf_from_net, &data, NULL);
2821 pending_error = ENOMEM;
2824 pending_error_text = xmalloc (80 + strlen (arg));
2825 if (pending_error_text == NULL)
2826 pending_error = ENOMEM;
2830 sprintf (pending_error_text,
2831 "E end of file reading notification for %s", arg);
2834 sprintf (pending_error_text,
2835 "E error reading notification for %s", arg);
2836 pending_error = status;
2840 free (new->filename);
2851 if (strchr (data, '+'))
2855 if (data[1] != '\t')
2860 cp = strchr (cp, '\t');
2864 cp = strchr (cp, '\t');
2868 cp = strchr (cp, '\t');
2873 /* If there is another tab, ignore everything after it,
2874 for future expansion. */
2875 cp = strchr (cp, '\t');
2881 if (last_node == NULL)
2884 last_node->next = new;
2890 if (alloc_pending (80))
2891 strcpy (pending_error_text,
2892 "E Protocol error; misformed Notify request");
2897 free (new->filename);
2898 free (new->update_dir);
2908 serve_hostname (char *arg)
2911 hostname = xstrdup (arg);
2918 serve_localdir (char *arg)
2920 if (CurDir) free (CurDir);
2921 CurDir = xstrdup (arg);
2926 /* Process all the Notify requests that we have stored up. Returns 0
2927 if successful, if not prints error message (via error()) and
2928 returns negative value. */
2930 server_notify (void)
2932 struct notify_note *p;
2935 TRACE (TRACE_FUNCTION, "server_notify()");
2937 while (notify_list != NULL)
2939 if (CVS_CHDIR (notify_list->dir) < 0)
2941 error (0, errno, "cannot change to %s", notify_list->dir);
2944 repos = Name_Repository (NULL, NULL);
2946 lock_dir_for_write (repos);
2948 fileattr_startdir (repos);
2950 notify_do (*notify_list->type, notify_list->filename,
2951 notify_list->update_dir, getcaller(), notify_list->val,
2952 notify_list->watches, repos);
2954 buf_output0 (buf_to_net, "Notified ");
2956 char *dir = notify_list->dir + strlen (server_temp_dir) + 1;
2958 buf_append_char (buf_to_net, '.');
2960 buf_output0 (buf_to_net, dir);
2961 buf_append_char (buf_to_net, '/');
2962 buf_append_char (buf_to_net, '\n');
2964 buf_output0 (buf_to_net, repos);
2965 buf_append_char (buf_to_net, '/');
2966 buf_output0 (buf_to_net, notify_list->filename);
2967 buf_append_char (buf_to_net, '\n');
2970 p = notify_list->next;
2971 free (notify_list->filename);
2972 free (notify_list->dir);
2973 free (notify_list->type);
2985 /* The code used to call fflush (stdout) here, but that is no
2986 longer necessary. The data is now buffered in buf_to_net,
2987 which will be flushed by the caller, do_cvs_command. */
2994 /* This request is processed in all passes since requests which must
2995 * sometimes be processed before it is known whether we are running as a
2996 * secondary or not, for instance the `expand-modules' request, sometimes use
3000 serve_argument (char *arg)
3004 if (error_pending()) return;
3006 if (argument_count >= 10000)
3008 if (alloc_pending (80))
3009 sprintf (pending_error_text,
3010 "E Protocol error: too many arguments");
3014 if (argument_vector_size <= argument_count)
3016 argument_vector_size *= 2;
3017 argument_vector = xnrealloc (argument_vector,
3018 argument_vector_size, sizeof (char *));
3019 if (argument_vector == NULL)
3021 pending_error = ENOMEM;
3025 p = xmalloc (strlen (arg) + 1);
3028 pending_error = ENOMEM;
3032 argument_vector[argument_count++] = p;
3037 /* For secondary servers, this is handled in all passes, as is the `Argument'
3038 * request, and for the same reasons.
3041 serve_argumentx (char *arg)
3045 if (error_pending()) return;
3047 if (argument_count <= 1)
3049 if (alloc_pending (80))
3050 sprintf (pending_error_text,
3051 "E Protocol error: called argumentx without prior call to argument");
3055 p = argument_vector[argument_count - 1];
3056 p = xrealloc (p, strlen (p) + 1 + strlen (arg) + 1);
3059 pending_error = ENOMEM;
3064 argument_vector[argument_count - 1] = p;
3070 serve_global_option (char *arg)
3072 # ifdef PROXY_SUPPORT
3073 /* This can generate error messages and termination before `Root' requests,
3074 * so it must be dealt with in the first pass.
3076 if (reprocessing) return;
3077 # endif /* PROXY_SUPPORT */
3079 if (arg[0] != '-' || arg[1] == '\0' || arg[2] != '\0')
3082 if (alloc_pending (strlen (arg) + 80))
3083 sprintf (pending_error_text,
3084 "E Protocol error: bad global option %s",
3091 error(0, 0, "WARNING: global `-l' option ignored.");
3116 /* This needs to be processed before Root requests, so we allow it to be
3117 * be processed before knowing whether we are running as a secondary server
3118 * to allow `noop' and `Root' requests to generate errors as before.
3121 serve_set (char *arg)
3123 # ifdef PROXY_SUPPORT
3124 if (reprocessing) return;
3125 # endif /* PROXY_SUPPORT */
3127 /* FIXME: This sends errors immediately (I think); they should be
3128 put into pending_error. */
3134 # ifdef HAVE_KERBEROS
3137 serve_kerberos_encrypt( char *arg )
3139 # ifdef PROXY_SUPPORT
3140 assert (!proxy_log);
3141 # endif /* PROXY_SUPPORT */
3143 /* All future communication with the client will be encrypted. */
3145 buf_to_net = krb_encrypt_buffer_initialize (buf_to_net, 0, sched,
3147 buf_to_net->memory_error);
3148 buf_from_net = krb_encrypt_buffer_initialize (buf_from_net, 1, sched,
3150 buf_from_net->memory_error);
3153 # endif /* HAVE_KERBEROS */
3158 serve_gssapi_encrypt( char *arg )
3160 # ifdef PROXY_SUPPORT
3161 assert (!proxy_log);
3162 # endif /* PROXY_SUPPORT */
3164 if (cvs_gssapi_wrapping)
3166 /* We're already using a gssapi_wrap buffer for stream
3167 authentication. Flush everything we've output so far, and
3168 turn on encryption for future data. On the input side, we
3169 should only have unwrapped as far as the Gssapi-encrypt
3170 command, so future unwrapping will become encrypted. */
3171 buf_flush (buf_to_net, 1);
3172 cvs_gssapi_encrypt = 1;
3176 /* All future communication with the client will be encrypted. */
3178 cvs_gssapi_encrypt = 1;
3180 buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
3182 buf_to_net->memory_error);
3183 buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
3185 buf_from_net->memory_error);
3187 cvs_gssapi_wrapping = 1;
3190 # endif /* HAVE_GSSAPI */
3192 # endif /* ENCRYPTION */
3197 serve_gssapi_authenticate (char *arg)
3199 # ifdef PROXY_SUPPORT
3200 assert (!proxy_log);
3201 # endif /* PROXY_SUPPORT */
3203 if (cvs_gssapi_wrapping)
3205 /* We're already using a gssapi_wrap buffer for encryption.
3206 That includes authentication, so we don't have to do
3207 anything further. */
3211 buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
3213 buf_to_net->memory_error);
3214 buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
3216 buf_from_net->memory_error);
3218 cvs_gssapi_wrapping = 1;
3221 # endif /* HAVE_GSSAPI */
3225 # ifdef SERVER_FLOWCONTROL
3226 /* The maximum we'll queue to the remote client before blocking. */
3227 # ifndef SERVER_HI_WATER
3228 # define SERVER_HI_WATER (2 * 1024 * 1024)
3229 # endif /* SERVER_HI_WATER */
3230 /* When the buffer drops to this, we restart the child */
3231 # ifndef SERVER_LO_WATER
3232 # define SERVER_LO_WATER (1 * 1024 * 1024)
3233 # endif /* SERVER_LO_WATER */
3234 # endif /* SERVER_FLOWCONTROL */
3239 serve_questionable (char *arg)
3243 # ifdef PROXY_SUPPORT
3244 if (proxy_log) return;
3245 # endif /* PROXY_SUPPORT */
3247 if (error_pending ()) return;
3251 /* Pick up ignores from CVSROOTADM_IGNORE, $HOME/.cvsignore on server,
3252 and CVSIGNORE on server. */
3257 if (gDirname == NULL)
3259 if (alloc_pending (80))
3260 sprintf (pending_error_text,
3261 "E Protocol error: `Directory' missing");
3265 if (outside_dir (arg))
3268 if (!ign_name (arg))
3272 buf_output (buf_to_net, "M ? ", 4);
3273 update_dir = gDirname + strlen (server_temp_dir) + 1;
3274 if (!(update_dir[0] == '.' && update_dir[1] == '\0'))
3276 buf_output0 (buf_to_net, update_dir);
3277 buf_output (buf_to_net, "/", 1);
3279 buf_output0 (buf_to_net, arg);
3280 buf_output (buf_to_net, "\n", 1);
3286 static struct buffer *protocol = NULL;
3288 /* This is the output which we are saving up to send to the server, in the
3289 child process. We will push it through, via the `protocol' buffer, when
3290 we have a complete line. */
3291 static struct buffer *saved_output;
3293 /* Likewise, but stuff which will go to stderr. */
3294 static struct buffer *saved_outerr;
3299 protocol_memory_error (struct buffer *buf)
3301 error (1, ENOMEM, "Virtual memory exhausted");
3306 /* If command is valid, return 1.
3307 * Else if command is invalid and croak_on_invalid is set, then die.
3308 * Else just return 0 to indicate that command is invalid.
3311 check_command_valid_p (char *cmd_name)
3313 /* Right now, only pserver notices invalid commands -- namely,
3314 * write attempts by a read-only user. Therefore, if CVS_Username
3315 * is not set, this just returns 1, because CVS_Username unset
3316 * means pserver is not active.
3318 # ifdef AUTH_SERVER_SUPPORT
3319 if (CVS_Username == NULL)
3322 if (lookup_command_attribute (cmd_name) & CVS_CMD_MODIFIES_REPOSITORY)
3324 /* This command has the potential to modify the repository, so
3325 * we check if the user have permission to do that.
3327 * (Only relevant for remote users -- local users can do
3328 * whatever normal Unix file permissions allow them to do.)
3330 * The decision method:
3332 * If $CVSROOT/CVSADMROOT_READERS exists and user is listed
3333 * in it, then read-only access for user.
3335 * Or if $CVSROOT/CVSADMROOT_WRITERS exists and user NOT
3336 * listed in it, then also read-only access for user.
3338 * Else read-write access for user.
3341 char *linebuf = NULL;
3343 size_t linebuf_len = 0;
3350 flen = strlen (current_parsed_root->directory)
3351 + strlen (CVSROOTADM)
3352 + strlen (CVSROOTADM_READERS)
3355 fname = xmalloc (flen);
3356 (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
3357 CVSROOTADM, CVSROOTADM_READERS);
3359 fp = fopen (fname, "r");
3363 if (!existence_error (errno))
3365 /* Need to deny access, so that attackers can't fool
3366 us with some sort of denial of service attack. */
3367 error (0, errno, "cannot open %s", fname);
3372 else /* successfully opened readers file */
3374 while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
3376 /* Hmmm, is it worth importing my own readline
3377 library into CVS? It takes care of chopping
3378 leading and trailing whitespace, "#" comments, and
3379 newlines automatically when so requested. Would
3380 save some code here... -kff */
3382 /* Chop newline by hand, for strcmp()'s sake. */
3383 if (num_red > 0 && linebuf[num_red - 1] == '\n')
3384 linebuf[num_red - 1] = '\0';
3386 if (strcmp (linebuf, CVS_Username) == 0)
3387 goto handle_invalid;
3389 if (num_red < 0 && !feof (fp))
3390 error (0, errno, "cannot read %s", fname);
3392 /* If not listed specifically as a reader, then this user
3393 has write access by default unless writers are also
3394 specified in a file . */
3395 if (fclose (fp) < 0)
3396 error (0, errno, "cannot close %s", fname);
3400 /* Now check the writers file. */
3402 flen = strlen (current_parsed_root->directory)
3403 + strlen (CVSROOTADM)
3404 + strlen (CVSROOTADM_WRITERS)
3407 fname = xmalloc (flen);
3408 (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
3409 CVSROOTADM, CVSROOTADM_WRITERS);
3411 fp = fopen (fname, "r");
3417 if (existence_error (errno))
3419 /* Writers file does not exist, so everyone is a writer,
3426 /* Need to deny access, so that attackers can't fool
3427 us with some sort of denial of service attack. */
3428 error (0, errno, "cannot read %s", fname);
3435 while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
3437 /* Chop newline by hand, for strcmp()'s sake. */
3438 if (num_red > 0 && linebuf[num_red - 1] == '\n')
3439 linebuf[num_red - 1] = '\0';
3441 if (strcmp (linebuf, CVS_Username) == 0)
3447 if (num_red < 0 && !feof (fp))
3448 error (0, errno, "cannot read %s", fname);
3452 if (fclose (fp) < 0)
3453 error (0, errno, "cannot close %s", fname);
3459 else /* writers file exists, but this user not listed in it */
3462 if (fclose (fp) < 0)
3463 error (0, errno, "cannot close %s", fname);
3470 # endif /* AUTH_SERVER_SUPPORT */
3472 /* If ever reach end of this function, command must be valid. */
3478 /* Execute COMMAND in a subprocess with the approriate funky things done. */
3480 static struct fd_set_wrapper { fd_set fds; } command_fds_to_drain;
3481 # ifdef SUNOS_KLUDGE
3482 static int max_command_fd;
3485 # ifdef SERVER_FLOWCONTROL
3486 static int flowcontrol_pipe[2];
3487 # endif /* SERVER_FLOWCONTROL */
3492 * Set buffer FD to non-blocking I/O. Returns 0 for success or errno
3496 set_nonblock_fd (int fd)
3498 # if defined (F_GETFL) && defined (O_NONBLOCK) && defined (F_SETFL)
3501 flags = fcntl (fd, F_GETFL, 0);
3504 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0)
3506 # endif /* F_GETFL && O_NONBLOCK && F_SETFL */
3513 do_cvs_command (char *cmd_name, int (*command) (int, char **))
3516 * The following file descriptors are set to -1 if that file is not
3520 /* Data on these pipes is a series of '\n'-terminated lines. */
3525 * Data on this pipe is a series of counted (see buf_send_counted)
3526 * packets. Each packet must be processed atomically (i.e. not
3527 * interleaved with data from stdout_pipe or stderr_pipe).
3529 int protocol_pipe[2];
3531 int dev_null_fd = -1;
3535 TRACE (TRACE_FUNCTION, "do_cvs_command (%s)", cmd_name);
3537 /* Write proxy logging is always terminated when a command is received.
3538 * Therefore, we wish to avoid reprocessing the command since that would
3539 * cause endless recursion.
3541 if ((command != version || current_parsed_root) && isProxyServer())
3543 # ifdef PROXY_SUPPORT
3545 /* This must be the second time we've reached this point.
3546 * Done reprocessing.
3548 reprocessing = false;
3551 if (lookup_command_attribute (cmd_name)
3552 & CVS_CMD_MODIFIES_REPOSITORY)
3555 exit (EXIT_SUCCESS);
3557 else if (/* serve_co may have called this already and missing logs
3558 * should have generated an error in serve_root().
3562 /* Set up the log for reprocessing. */
3563 rewind_buf_from_net ();
3564 /* And return to the main loop in server(), where we will now
3565 * find the logged secondary data and reread it.
3570 # else /* !PROXY_SUPPORT */
3571 if (lookup_command_attribute (cmd_name)
3572 & CVS_CMD_MODIFIES_REPOSITORY
3573 && alloc_pending (120))
3574 sprintf (pending_error_text,
3575 "E You need a CVS client that supports the `Redirect' response for write requests to this server.");
3577 # endif /* PROXY_SUPPORT */
3581 stdout_pipe[0] = -1;
3582 stdout_pipe[1] = -1;
3583 stderr_pipe[0] = -1;
3584 stderr_pipe[1] = -1;
3585 protocol_pipe[0] = -1;
3586 protocol_pipe[1] = -1;
3588 server_write_entries ();
3590 if (print_pending_error ())
3591 goto free_args_and_return;
3593 /* Global `cvs_cmd_name' is probably "server" right now -- only
3594 serve_export() sets it to anything else. So we will use local
3595 parameter `cmd_name' to determine if this command is valid for
3597 if (!check_command_valid_p (cmd_name))
3599 buf_output0 (buf_to_net, "E ");
3600 buf_output0 (buf_to_net, program_name);
3601 buf_output0 (buf_to_net, " [server aborted]: \"");
3602 buf_output0 (buf_to_net, cmd_name);
3603 buf_output0 (buf_to_net,
3604 "\" requires write access to the repository\n\
3606 goto free_args_and_return;
3608 cvs_cmd_name = cmd_name;
3610 (void) server_notify ();
3613 * We use a child process which actually does the operation. This
3614 * is so we can intercept its standard output. Even if all of CVS
3615 * were written to go to some special routine instead of writing
3616 * to stdout or stderr, we would still need to do the same thing
3617 * for the RCS commands.
3620 if (pipe (stdout_pipe) < 0)
3622 buf_output0 (buf_to_net, "E pipe failed\n");
3623 print_error (errno);
3626 if (pipe (stderr_pipe) < 0)
3628 buf_output0 (buf_to_net, "E pipe failed\n");
3629 print_error (errno);
3632 if (pipe (protocol_pipe) < 0)
3634 buf_output0 (buf_to_net, "E pipe failed\n");
3635 print_error (errno);
3638 # ifdef SERVER_FLOWCONTROL
3639 if (pipe (flowcontrol_pipe) < 0)
3641 buf_output0 (buf_to_net, "E pipe failed\n");
3642 print_error (errno);
3645 set_nonblock_fd (flowcontrol_pipe[0]);
3646 set_nonblock_fd (flowcontrol_pipe[1]);
3647 # endif /* SERVER_FLOWCONTROL */
3649 dev_null_fd = CVS_OPEN (DEVNULL, O_RDONLY);
3650 if (dev_null_fd < 0)
3652 buf_output0 (buf_to_net, "E open /dev/null failed\n");
3653 print_error (errno);
3657 /* We shouldn't have any partial lines from cvs_output and
3658 cvs_outerr, but we handle them here in case there is a bug. */
3659 /* FIXME: appending a newline, rather than using "MT" as we
3660 do in the child process, is probably not really a very good
3661 way to "handle" them. */
3662 if (! buf_empty_p (saved_output))
3664 buf_append_char (saved_output, '\n');
3665 buf_copy_lines (buf_to_net, saved_output, 'M');
3667 if (! buf_empty_p (saved_outerr))
3669 buf_append_char (saved_outerr, '\n');
3670 buf_copy_lines (buf_to_net, saved_outerr, 'E');
3673 /* Flush out any pending data. */
3674 buf_flush (buf_to_net, 1);
3676 /* Don't use vfork; we're not going to exec(). */
3677 command_pid = fork ();
3678 if (command_pid < 0)
3680 buf_output0 (buf_to_net, "E fork failed\n");
3681 print_error (errno);
3684 if (command_pid == 0)
3688 /* Since we're in the child, and the parent is going to take
3689 care of packaging up our error messages, we can clear this
3691 error_use_protocol = 0;
3693 protocol = fd_buffer_initialize (protocol_pipe[1], 0, NULL, false,
3694 protocol_memory_error);
3696 /* At this point we should no longer be using buf_to_net and
3697 buf_from_net. Instead, everything should go through
3699 if (buf_to_net != NULL)
3701 buf_free (buf_to_net);
3704 if (buf_from_net != NULL)
3706 buf_free (buf_from_net);
3707 buf_from_net = NULL;
3710 /* These were originally set up to use outbuf_memory_error.
3711 Since we're now in the child, we should use the simpler
3712 protocol_memory_error function. */
3713 saved_output->memory_error = protocol_memory_error;
3714 saved_outerr->memory_error = protocol_memory_error;
3716 if (dup2 (dev_null_fd, STDIN_FILENO) < 0)
3717 error (1, errno, "can't set up pipes");
3718 if (dup2 (stdout_pipe[1], STDOUT_FILENO) < 0)
3719 error (1, errno, "can't set up pipes");
3720 if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
3721 error (1, errno, "can't set up pipes");
3722 close (dev_null_fd);
3723 close (stdout_pipe[0]);
3724 close (stdout_pipe[1]);
3725 close (stderr_pipe[0]);
3726 close (stderr_pipe[1]);
3727 close (protocol_pipe[0]);
3728 close_on_exec (protocol_pipe[1]);
3729 # ifdef SERVER_FLOWCONTROL
3730 close_on_exec (flowcontrol_pipe[0]);
3731 close (flowcontrol_pipe[1]);
3732 # endif /* SERVER_FLOWCONTROL */
3735 * Set this in .bashrc if you want to give yourself time to attach
3736 * to the subprocess with a debugger.
3738 if (getenv("CVS_SERVER_SLEEP") && *getenv("CVS_SERVER_SLEEP"))
3740 int secs = atoi (getenv ("CVS_SERVER_SLEEP"));
3741 TRACE (TRACE_DATA, "Sleeping CVS_SERVER_SLEEP (%d) seconds", secs);
3745 TRACE (TRACE_DATA, "CVS_SERVER_SLEEP not set.");
3747 exitstatus = (*command) (argument_count, argument_vector);
3749 /* Output any partial lines. If the client doesn't support
3750 "MT", we go ahead and just tack on a newline since the
3751 protocol doesn't support anything better. */
3752 if (! buf_empty_p (saved_output))
3754 buf_output0 (protocol, supported_response ("MT") ? "MT text " : "M ");
3755 buf_append_buffer (protocol, saved_output);
3756 buf_output (protocol, "\n", 1);
3757 buf_send_counted (protocol);
3759 /* For now we just discard partial lines on stderr. I suspect
3760 that CVS can't write such lines unless there is a bug. */
3762 buf_free (protocol);
3764 /* Close the pipes explicitly in order to send an EOF to the parent,
3765 * then wait for the parent to close the flow control pipe. This
3766 * avoids a race condition where a child which dumped more than the
3767 * high water mark into the pipes could complete its job and exit,
3768 * leaving the parent process to attempt to write a stop byte to the
3769 * closed flow control pipe, which earned the parent a SIGPIPE, which
3770 * it normally only expects on the network pipe and that causes it to
3771 * exit with an error message, rather than the SIGCHILD that it knows
3772 * how to handle correctly.
3774 /* Let exit() close STDIN - it's from /dev/null anyhow. */
3777 close (protocol_pipe[1]);
3778 # ifdef SERVER_FLOWCONTROL
3782 while ((status = read (flowcontrol_pipe[0], &junk, 1)) > 0
3783 || (status == -1 && errno == EAGAIN));
3785 /* FIXME: No point in printing an error message with error(),
3786 * as STDERR is already closed, but perhaps this could be syslogged?
3793 /* OK, sit around getting all the input from the child. */
3795 struct buffer *stdoutbuf;
3796 struct buffer *stderrbuf;
3797 struct buffer *protocol_inbuf;
3798 /* Number of file descriptors to check in select (). */
3800 int count_needed = 1;
3801 # ifdef SERVER_FLOWCONTROL
3802 int have_flowcontrolled = 0;
3803 # endif /* SERVER_FLOWCONTROL */
3805 FD_ZERO (&command_fds_to_drain.fds);
3806 num_to_check = stdout_pipe[0];
3807 FD_SET (stdout_pipe[0], &command_fds_to_drain.fds);
3808 num_to_check = MAX (num_to_check, stderr_pipe[0]);
3809 FD_SET (stderr_pipe[0], &command_fds_to_drain.fds);
3810 num_to_check = MAX (num_to_check, protocol_pipe[0]);
3811 FD_SET (protocol_pipe[0], &command_fds_to_drain.fds);
3812 num_to_check = MAX (num_to_check, STDOUT_FILENO);
3813 # ifdef SUNOS_KLUDGE
3814 max_command_fd = num_to_check;
3817 * File descriptors are numbered from 0, so num_to_check needs to
3818 * be one larger than the largest descriptor.
3821 if (num_to_check > FD_SETSIZE)
3823 buf_output0 (buf_to_net,
3824 "E internal error: FD_SETSIZE not big enough.\n\
3829 stdoutbuf = fd_buffer_initialize (stdout_pipe[0], 0, NULL, true,
3830 input_memory_error);
3832 stderrbuf = fd_buffer_initialize (stderr_pipe[0], 0, NULL, true,
3833 input_memory_error);
3835 protocol_inbuf = fd_buffer_initialize (protocol_pipe[0], 0, NULL, true,
3836 input_memory_error);
3838 set_nonblock (buf_to_net);
3839 set_nonblock (stdoutbuf);
3840 set_nonblock (stderrbuf);
3841 set_nonblock (protocol_inbuf);
3843 if (close (stdout_pipe[1]) < 0)
3845 buf_output0 (buf_to_net, "E close failed\n");
3846 print_error (errno);
3849 stdout_pipe[1] = -1;
3851 if (close (stderr_pipe[1]) < 0)
3853 buf_output0 (buf_to_net, "E close failed\n");
3854 print_error (errno);
3857 stderr_pipe[1] = -1;
3859 if (close (protocol_pipe[1]) < 0)
3861 buf_output0 (buf_to_net, "E close failed\n");
3862 print_error (errno);
3865 protocol_pipe[1] = -1;
3867 # ifdef SERVER_FLOWCONTROL
3868 if (close (flowcontrol_pipe[0]) < 0)
3870 buf_output0 (buf_to_net, "E close failed\n");
3871 print_error (errno);
3874 flowcontrol_pipe[0] = -1;
3875 # endif /* SERVER_FLOWCONTROL */