6ef9bae6f31c9ba78ded5899f4274b959ce61009
[alioth/cvs.git] / src / server.c
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 __RCSID("$MirOS: src/gnu/usr.bin/cvs/src/server.c,v 1.10 2016/11/08 21:46:14 tg Exp $");
24
25 int server_active = 0;
26
27 #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
28
29 # include "log-buffer.h"
30 # include "ms-buffer.h"
31 #endif  /* defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) */
32
33 #if defined (HAVE_GSSAPI) && defined (SERVER_SUPPORT)
34 # include "canon-host.h"
35 # include "gssapi-client.h"
36
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
39  * support.
40  *
41  * FIXME - They should be in a different file.
42  */
43 /* We use Kerberos 5 routines to map the GSSAPI credential to a user
44    name.  */
45 # include <krb5.h>
46
47 static void gserver_authenticate_connection (void);
48
49 /* Whether we are already wrapping GSSAPI communication.  */
50 static int cvs_gssapi_wrapping;
51
52 #endif  /* defined (HAVE_GSSAPI) && defined (SERVER_SUPPORT) */
53
54 #ifdef SERVER_SUPPORT
55
56 extern char *server_hostname;
57
58 # if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
59 #   include <sys/socket.h>
60 # endif
61
62 # ifdef HAVE_SYSLOG_H
63 #   include <syslog.h>
64 #   ifndef LOG_DAEMON   /* for ancient syslogs */
65 #     define LOG_DAEMON 0
66 #   endif
67 # endif /* HAVE_SYSLOG_H */
68
69 # ifdef HAVE_KERBEROS
70 #   include <netinet/in.h>
71 #   include <krb.h>
72 #   ifndef HAVE_KRB_GET_ERR_TEXT
73 #     define krb_get_err_text(status) krb_err_txt[status]
74 #   endif
75
76 /* Information we need if we are going to use Kerberos encryption.  */
77 static C_Block kblock;
78 static Key_schedule sched;
79
80 # endif /* HAVE_KERBEROS */
81
82 /* for select */
83 # include "xselect.h"
84
85 /* for TCP_NODELAY */
86 #include <netinet/tcp.h>
87
88 # ifndef O_NONBLOCK
89 #   define O_NONBLOCK O_NDELAY
90 # endif
91
92 /* For initgroups().  */
93 # if HAVE_INITGROUPS
94 #   include <grp.h>
95 # endif /* HAVE_INITGROUPS */
96
97 # ifdef AUTH_SERVER_SUPPORT
98
99 #   ifdef HAVE_GETSPNAM
100 #     include <shadow.h>
101 #   endif
102
103 /* The cvs username sent by the client, which might or might not be
104    the same as the system username the server eventually switches to
105    run as.  CVS_Username gets set iff password authentication is
106    successful. */
107 char *CVS_Username = NULL;
108
109 /* Used to check that same repos is transmitted in pserver auth and in
110    later CVS protocol.  Exported because root.c also uses. */
111 static char *Pserver_Repos = NULL;
112
113 # endif /* AUTH_SERVER_SUPPORT */
114
115 # ifdef HAVE_PAM
116 #   if defined(HAVE_SECURITY_PAM_APPL_H)
117 #     include <security/pam_appl.h>
118 #   elif defined(HAVE_PAM_PAM_APPL_H)
119 #     include <pam/pam_appl.h>
120 #   endif
121
122 static pam_handle_t *pamh = NULL;
123
124 static char *pam_username;
125 static char *pam_password;
126 # endif /* HAVE_PAM */
127
128
129
130 /* While processing requests, this buffer accumulates data to be sent to
131    the client, and then once we are in do_cvs_command, we use it
132    for all the data to be sent.  */
133 static struct buffer *buf_to_net;
134
135 /* This buffer is used to read input from the client.  */
136 static struct buffer *buf_from_net;
137
138
139
140 # ifdef PROXY_SUPPORT
141 /* These are the secondary log buffers so that we can disable them after
142  * creation, when it is determined that they are unneeded, regardless of what
143  * other filters have been prepended to the buffer chain.
144  */
145 static struct buffer *proxy_log;
146 static struct buffer *proxy_log_out;
147
148 /* Set while we are reprocessing a log so that we can avoid sending responses
149  * to some requests twice.
150  */
151 static bool reprocessing;
152 # endif /* PROXY_SUPPORT */
153
154
155
156 /* Arguments storage for `Argument' & `Argumentx' requests.  */
157 static int argument_count;
158 static char **argument_vector;
159 static int argument_vector_size;
160
161 /*
162  * This is where we stash stuff we are going to use.  Format string
163  * which expects a single directory within it, starting with a slash.
164  */
165 static char *server_temp_dir;
166
167 /* This is the original value of server_temp_dir, before any possible
168    changes inserted by serve_max_dotdot.  */
169 static char *orig_server_temp_dir;
170
171 /* Nonzero if we should keep the temp directory around after we exit.  */
172 static int dont_delete_temp;
173
174 static void server_write_entries (void);
175
176 cvsroot_t *referrer;
177
178
179
180 /* Populate all of the directories between BASE_DIR and its relative
181    subdirectory DIR with CVSADM directories.  Return 0 for success or
182    errno value.  */
183 static int
184 create_adm_p (char *base_dir, char *dir)
185 {
186     char *dir_where_cvsadm_lives, *dir_to_register, *p, *tmp;
187     int retval, done;
188     FILE *f;
189
190     if (strcmp (dir, ".") == 0)
191         return 0;                       /* nothing to do */
192
193     /* Allocate some space for our directory-munging string. */
194     p = xmalloc (strlen (dir) + 1);
195     if (p == NULL)
196         return ENOMEM;
197
198     dir_where_cvsadm_lives = xmalloc (strlen (base_dir) + strlen (dir) + 100);
199     if (dir_where_cvsadm_lives == NULL)
200     {
201         free (p);
202         return ENOMEM;
203     }
204
205     /* Allocate some space for the temporary string in which we will
206        construct filenames. */
207     tmp = xmalloc (strlen (base_dir) + strlen (dir) + 100);
208     if (tmp == NULL)
209     {
210         free (p);
211         free (dir_where_cvsadm_lives);
212         return ENOMEM;
213     }
214
215
216     /* We make several passes through this loop.  On the first pass,
217        we simply create the CVSADM directory in the deepest directory.
218        For each subsequent pass, we try to remove the last path
219        element from DIR, create the CVSADM directory in the remaining
220        pathname, and register the subdirectory in the newly created
221        CVSADM directory. */
222
223     retval = done = 0;
224
225     strcpy (p, dir);
226     strcpy (dir_where_cvsadm_lives, base_dir);
227     strcat (dir_where_cvsadm_lives, "/");
228     strcat (dir_where_cvsadm_lives, p);
229     dir_to_register = NULL;
230
231     while (1)
232     {
233         /* Create CVSADM. */
234         (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM);
235         if ((CVS_MKDIR (tmp, 0777) < 0) && (errno != EEXIST))
236         {
237             retval = errno;
238             goto finish;
239         }
240
241         /* Create CVSADM_REP. */
242         (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_REP);
243         if (! isfile (tmp))
244         {
245             /* Use Emptydir as the placeholder until the client sends
246                us the real value.  This code is similar to checkout.c
247                (emptydir_name), but the code below returns errors
248                differently.  */
249
250             char *empty;
251             empty = xmalloc (strlen (current_parsed_root->directory)
252                             + sizeof (CVSROOTADM)
253                             + sizeof (CVSNULLREPOS)
254                             + 3);
255             if (! empty)
256             {
257                 retval = ENOMEM;
258                 goto finish;
259             }
260
261             /* Create the directory name. */
262             (void) sprintf (empty, "%s/%s/%s", current_parsed_root->directory,
263                             CVSROOTADM, CVSNULLREPOS);
264
265             /* Create the directory if it doesn't exist. */
266             if (! isfile (empty))
267             {
268                 mode_t omask;
269                 omask = umask (cvsumask);
270                 if (CVS_MKDIR (empty, 0777) < 0)
271                 {
272                     retval = errno;
273                     free (empty);
274                     goto finish;
275                 }
276                 (void) umask (omask);
277             }
278
279             f = CVS_FOPEN (tmp, "w");
280             if (f == NULL)
281             {
282                 retval = errno;
283                 free (empty);
284                 goto finish;
285             }
286             /* Write the directory name to CVSADM_REP. */
287             if (fprintf (f, "%s\n", empty) < 0)
288             {
289                 retval = errno;
290                 fclose (f);
291                 free (empty);
292                 goto finish;
293             }
294             if (fclose (f) == EOF)
295             {
296                 retval = errno;
297                 free (empty);
298                 goto finish;
299             }
300
301             /* Clean up after ourselves. */
302             free (empty);
303         }
304
305         /* Create CVSADM_ENT.  We open in append mode because we
306            don't want to clobber an existing Entries file.  */
307         (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_ENT);
308         f = CVS_FOPEN (tmp, "a");
309         if (f == NULL)
310         {
311             retval = errno;
312             goto finish;
313         }
314         if (fclose (f) == EOF)
315         {
316             retval = errno;
317             goto finish;
318         }
319
320         if (dir_to_register != NULL)
321         {
322             /* FIXME: Yes, this results in duplicate entries in the
323                Entries.Log file, but it doesn't currently matter.  We
324                might need to change this later on to make sure that we
325                only write one entry.  */
326
327             Subdir_Register (NULL, dir_where_cvsadm_lives, dir_to_register);
328         }
329
330         if (done)
331             break;
332
333         dir_to_register = strrchr (p, '/');
334         if (dir_to_register == NULL)
335         {
336             dir_to_register = p;
337             strcpy (dir_where_cvsadm_lives, base_dir);
338             done = 1;
339         }
340         else
341         {
342             *dir_to_register = '\0';
343             dir_to_register++;
344             strcpy (dir_where_cvsadm_lives, base_dir);
345             strcat (dir_where_cvsadm_lives, "/");
346             strcat (dir_where_cvsadm_lives, p);
347         }
348     }
349
350   finish:
351     free (tmp);
352     free (dir_where_cvsadm_lives);
353     free (p);
354     return retval;
355 }
356
357
358
359 /*
360  * Make directory DIR, including all intermediate directories if necessary.
361  * Returns 0 for success or errno code.
362  */
363 static int
364 mkdir_p (char *dir)
365 {
366     char *p;
367     char *q = xmalloc (strlen (dir) + 1);
368     int retval;
369
370     if (q == NULL)
371         return ENOMEM;
372
373     retval = 0;
374
375     /*
376      * Skip over leading slash if present.  We won't bother to try to
377      * make '/'.
378      */
379     p = dir + 1;
380     while (1)
381     {
382         while (*p != '/' && *p != '\0')
383             ++p;
384         if (*p == '/')
385         {
386             strncpy (q, dir, p - dir);
387             q[p - dir] = '\0';
388             if (q[p - dir - 1] != '/'  &&  CVS_MKDIR (q, 0777) < 0)
389             {
390                 int saved_errno = errno;
391
392                 if (saved_errno != EEXIST
393                     && ((saved_errno != EACCES && saved_errno != EROFS)
394                         || !isdir (q)))
395                 {
396                     retval = saved_errno;
397                     goto done;
398                 }
399             }
400             ++p;
401         }
402         else
403         {
404             if (CVS_MKDIR (dir, 0777) < 0)
405                 retval = errno;
406             goto done;
407         }
408     }
409   done:
410     free (q);
411     return retval;
412 }
413
414
415
416 /*
417  * Print the error response for error code STATUS.  The caller is
418  * reponsible for making sure we get back to the command loop without
419  * any further output occuring.
420  * Must be called only in contexts where it is OK to send output.
421  */
422 static void
423 print_error (int status)
424 {
425     char *msg;
426     char tmpstr[80];
427
428     buf_output0 (buf_to_net, "error  ");
429     msg = strerror (status);
430     if (msg == NULL)
431     {
432        sprintf (tmpstr, "unknown error %d", status);
433        msg = tmpstr;
434     }
435     buf_output0 (buf_to_net, msg);
436     buf_append_char (buf_to_net, '\n');
437
438     buf_flush (buf_to_net, 0);
439 }
440
441
442
443 static int pending_error;
444 /*
445  * Malloc'd text for pending error.  Each line must start with "E ".  The
446  * last line should not end with a newline.
447  */
448 static char *pending_error_text;
449 static char *pending_warning_text;
450
451 /* If an error is pending, print it and return 1.  If not, return 0.
452    Also prints pending warnings, but this does not affect the return value.
453    Must be called only in contexts where it is OK to send output.  */
454 static int
455 print_pending_error (void)
456 {
457     /* Check this case first since it usually means we are out of memory and
458      * the buffer output routines might try and allocate memory.
459      */
460     if (!pending_error_text && pending_error)
461     {
462         print_error (pending_error);
463         pending_error = 0;
464         return 1;
465     }
466
467     if (pending_warning_text)
468     {
469         buf_output0 (buf_to_net, pending_warning_text);
470         buf_append_char (buf_to_net, '\n');
471         buf_flush (buf_to_net, 0);
472
473         free (pending_warning_text);
474         pending_warning_text = NULL;
475     }
476
477     if (pending_error_text)
478     {
479         buf_output0 (buf_to_net, pending_error_text);
480         buf_append_char (buf_to_net, '\n');
481         if (pending_error)
482             print_error (pending_error);
483         else
484             buf_output0 (buf_to_net, "error  \n");
485
486         buf_flush (buf_to_net, 0);
487
488         pending_error = 0;
489         free (pending_error_text);
490         pending_error_text = NULL;
491         return 1;
492     }
493
494     return 0;
495 }
496
497
498
499 /* Is an error pending?  */
500 # define error_pending() (pending_error || pending_error_text)
501 # define warning_pending() (pending_warning_text)
502
503 /* Allocate SIZE bytes for pending_error_text and return nonzero
504    if we could do it.  */
505 static inline int
506 alloc_pending_internal (char **dest, size_t size)
507 {
508     *dest = malloc (size);
509     if (!*dest)
510     {
511         pending_error = ENOMEM;
512         return 0;
513     }
514     return 1;
515 }
516
517
518
519 /* Allocate SIZE bytes for pending_error_text and return nonzero
520    if we could do it.  */
521 static int
522 alloc_pending (size_t size)
523 {
524     if (error_pending ())
525         /* Probably alloc_pending callers will have already checked for
526            this case.  But we might as well handle it if they don't, I
527            guess.  */
528         return 0;
529     return alloc_pending_internal (&pending_error_text, size);
530 }
531
532
533
534 /* Allocate SIZE bytes for pending_error_text and return nonzero
535    if we could do it.  */
536 static int
537 alloc_pending_warning (size_t size)
538 {
539     if (warning_pending ())
540         /* Warnings can be lost here.  */
541         return 0;
542     return alloc_pending_internal (&pending_warning_text, size);
543 }
544
545
546
547 static int
548 supported_response (char *name)
549 {
550     struct response *rs;
551
552     for (rs = responses; rs->name != NULL; ++rs)
553         if (strcmp (rs->name, name) == 0)
554             return rs->status == rs_supported;
555     error (1, 0, "internal error: testing support for unknown response?");
556     /* NOTREACHED */
557     return 0;
558 }
559
560
561
562 /*
563  * Return true if we need to relay write requests to a primary server
564  * and false otherwise.
565  *
566  * NOTES
567  *
568  *   - primarily handles :ext: method as this seems most likely to be used in
569  *     practice.
570  *
571  *   - :fork: method is handled for testing.
572  *
573  *   - Could handle pserver too, but would have to store the password
574  *     the client sent us.
575  *
576  *
577  * GLOBALS
578  *   config->PrimaryServer
579  *                        The parsed setting from CVSROOT/config, if any, or
580  *                        NULL, otherwise.
581  *   current_parsed_root  The current repository.
582  *
583  * RETURNS
584  *   true                 If this server is configured as a secondary server.
585  *   false                Otherwise.
586  */
587 static inline bool
588 isProxyServer (void)
589 {
590     assert (current_parsed_root);
591
592     /***
593      *** The following is done as a series of if/return combinations an an
594      *** optimization.
595      ***/
596
597     /* If there is no primary server defined in CVSROOT/config, then we can't
598      * be a secondary.
599      */
600     if (!config || !config->PrimaryServer) return false;
601
602     /* The directory must not match for all methods.  */
603     if (!isSamePath (config->PrimaryServer->directory,
604                      current_parsed_root->directory))
605         return true;
606
607     /* Only the directory is important for fork.  */
608     if (config->PrimaryServer->method == fork_method)
609         return false;
610
611     /* Must be :ext: method, then.  This is enforced when CVSROOT/config is
612      * parsed.
613      */
614     assert (config->PrimaryServer->isremote);
615
616     if (isThisHost (config->PrimaryServer->hostname))
617         return false;
618
619     return true;
620 }
621
622
623
624 static void
625 serve_valid_responses (char *arg)
626 {
627     char *p = arg;
628     char *q;
629     struct response *rs;
630
631 # ifdef PROXY_SUPPORT
632     /* Process this in the first pass since the data it gathers can be used
633      * prior to a `Root' request.
634      */
635     if (reprocessing) return;
636 # endif /* PROXY_SUPPORT */
637
638     do
639     {
640         q = strchr (p, ' ');
641         if (q != NULL)
642             *q++ = '\0';
643         for (rs = responses; rs->name != NULL; ++rs)
644         {
645             if (strcmp (rs->name, p) == 0)
646                 break;
647         }
648         if (rs->name == NULL)
649             /*
650              * It is a response we have never heard of (and thus never
651              * will want to use).  So don't worry about it.
652              */
653             ;
654         else
655             rs->status = rs_supported;
656         p = q;
657     } while (q != NULL);
658     for (rs = responses; rs->name != NULL; ++rs)
659     {
660         if (rs->status == rs_essential)
661         {
662             buf_output0 (buf_to_net, "E response `");
663             buf_output0 (buf_to_net, rs->name);
664             buf_output0 (buf_to_net, "' not supported by client\nerror  \n");
665
666             /* FIXME: This call to buf_flush could conceivably
667                cause deadlock, as noted in server_cleanup.  */
668             buf_flush (buf_to_net, 1);
669
670             exit (EXIT_FAILURE);
671         }
672         else if (rs->status == rs_optional)
673             rs->status = rs_not_supported;
674     }
675 }
676
677
678
679 /*
680  * Process IDs of the subprocess, or negative if that subprocess
681  * does not exist.
682  */
683 static pid_t command_pid;
684
685 static void
686 outbuf_memory_error (struct buffer *buf)
687 {
688     static const char msg[] = "E Fatal server error\n\
689 error ENOMEM Virtual memory exhausted.\n";
690     if (command_pid > 0)
691         kill (command_pid, SIGTERM);
692
693     /*
694      * We have arranged things so that printing this now either will
695      * be valid, or the "E fatal error" line will get glommed onto the
696      * end of an existing "E" or "M" response.
697      */
698
699     /* If this gives an error, not much we could do.  syslog() it?  */
700     write (STDOUT_FILENO, msg, sizeof (msg) - 1);
701 # ifdef HAVE_SYSLOG_H
702     syslog (LOG_DAEMON | LOG_ERR, "virtual memory exhausted");
703 # endif /* HAVE_SYSLOG_H */
704     exit (EXIT_FAILURE);
705 }
706
707
708
709 static void
710 input_memory_error (struct buffer *buf)
711 {
712     outbuf_memory_error (buf);
713 }
714
715
716
717 # ifdef PROXY_SUPPORT
718 /* This function rewinds the net connection using the write proxy log file.
719  *
720  * GLOBALS
721  *   proxy_log  The buffer object containing the write proxy log.
722  *
723  * RETURNS
724  *   Nothing.
725  */
726 static void
727 rewind_buf_from_net (void)
728 {
729     struct buffer *log;
730
731     assert (proxy_log);
732
733     /* Free the arguments since we processed some of them in the first pass.
734      */
735     {
736         /* argument_vector[0] is a dummy argument, we don't mess with
737          * it.
738          */
739         char **cp;
740         for (cp = argument_vector + 1;
741              cp < argument_vector + argument_count;
742              ++cp)
743             free (*cp);
744
745         argument_count = 1;
746     }
747
748     log = log_buffer_rewind (proxy_log);
749     proxy_log = NULL;
750     /* Dispose of any read but unused data in the net buffer since it will
751      * already be in the log.
752      */
753     buf_free_data (buf_from_net);
754     buf_from_net = ms_buffer_initialize (outbuf_memory_error, log,
755                                          buf_from_net);
756     reprocessing = true;
757 }
758 # endif /* PROXY_SUPPORT */
759
760
761
762 char *gConfigPath;
763
764
765
766 /*
767  * This request cannot be ignored by a potential secondary since it is used to
768  * determine if we _are_ a secondary.
769  */
770 static void
771 serve_root (char *arg)
772 {
773     char *path;
774
775     TRACE (TRACE_FUNCTION, "serve_root (%s)", arg ? arg : "(null)");
776
777     /* Don't process this twice or when errors are pending.  */
778     if (error_pending()
779 # ifdef PROXY_SUPPORT
780         || reprocessing
781 # endif /* PROXY_SUPPORT */
782        ) return;
783
784     if (!ISABSOLUTE (arg))
785     {
786         if (alloc_pending (80 + strlen (arg)))
787             sprintf (pending_error_text,
788                      "E Root %s must be an absolute pathname", arg);
789         return;
790     }
791
792     /* Sending "Root" twice is invalid.
793
794        The other way to handle a duplicate Root requests would be as a
795        request to clear out all state and start over as if it was a
796        new connection.  Doing this would cause interoperability
797        headaches, so it should be a different request, if there is
798        any reason why such a feature is needed.  */
799     if (current_parsed_root != NULL)
800     {
801         if (alloc_pending (80 + strlen (arg)))
802             sprintf (pending_error_text,
803                      "E Protocol error: Duplicate Root request, for %s", arg);
804         return;
805     }
806
807     /* Set original_parsed_root here, not because it can be changed in the
808      * client Redirect sense, but so we don't have to switch in code that
809      * runs in both modes to decide which to print.
810      */
811     original_parsed_root = current_parsed_root = local_cvsroot (arg);
812
813 # ifdef AUTH_SERVER_SUPPORT
814     if (Pserver_Repos != NULL)
815     {
816         if (strcmp (Pserver_Repos, current_parsed_root->directory) != 0)
817         {
818             if (alloc_pending (80 + strlen (Pserver_Repos)
819                                + strlen (current_parsed_root->directory)))
820                 /* The explicitness is to aid people who are writing clients.
821                    I don't see how this information could help an
822                    attacker.  */
823                 sprintf (pending_error_text, "\
824 E Protocol error: Root says \"%s\" but pserver says \"%s\"",
825                          current_parsed_root->directory, Pserver_Repos);
826             return;
827         }
828     }
829 # endif
830
831     if (root_allow_used() && !root_allow_ok(arg))
832     {
833         if (alloc_pending (80 + strlen (arg)))
834             sprintf (pending_error_text,
835                      "E Bad root %s", arg);
836         return;
837     }
838
839     /* For pserver, this will already have happened, and the call will do
840        nothing.  But for rsh, we need to do it now.  */
841     config = get_root_allow_config (current_parsed_root->directory,
842                                     gConfigPath);
843
844 # ifdef PROXY_SUPPORT
845     /* At this point we have enough information to determine if we are a
846      * secondary server or not.
847      */
848     if (proxy_log && !isProxyServer ())
849     {
850         /* Else we are not a secondary server.  There is no point in
851          * reprocessing since we handle all the requests we can receive
852          * before `Root' as we receive them.  But close the logs.
853          */
854         log_buffer_closelog (proxy_log);
855         log_buffer_closelog (proxy_log_out);
856         proxy_log = NULL;
857         /*
858          * Don't need this.  We assume it when proxy_log == NULL.
859          *
860          *   proxy_log_out = NULL;
861          */
862     }
863 # endif /* PROXY_SUPPORT */
864
865     /* Now set the TMPDIR environment variable.  If it was set in the config
866      * file, we now know it.
867      */
868     push_env_temp_dir ();
869
870     /* OK, now figure out where we stash our temporary files.  */
871     {
872         char *p;
873
874         /* The code which wants to chdir into server_temp_dir is not set
875          * up to deal with it being a relative path.  So give an error
876          * for that case.
877          */
878         if (!ISABSOLUTE (get_cvs_tmp_dir ()))
879         {
880             if (alloc_pending (80 + strlen (get_cvs_tmp_dir ())))
881                 sprintf (pending_error_text,
882                          "E Value of %s for TMPDIR is not absolute",
883                          get_cvs_tmp_dir ());
884
885             /* FIXME: we would like this error to be persistent, that
886              * is, not cleared by print_pending_error.  The current client
887              * will exit as soon as it gets an error, but the protocol spec
888              * does not require a client to do so.
889              */
890         }
891         else
892         {
893             int status;
894             int i = 0;
895
896             server_temp_dir = xmalloc (strlen (get_cvs_tmp_dir ()) + 80);
897             if (!server_temp_dir)
898             {
899                 /* Strictly speaking, we're not supposed to output anything
900                  * now.  But we're about to exit(), give it a try.
901                  */
902                 printf ("E Fatal server error, aborting.\n\
903 error ENOMEM Virtual memory exhausted.\n");
904
905                 exit (EXIT_FAILURE);
906             }
907             strcpy (server_temp_dir, get_cvs_tmp_dir ());
908
909             /* Remove a trailing slash from TMPDIR if present.  */
910             p = server_temp_dir + strlen (server_temp_dir) - 1;
911             if (*p == '/')
912                 *p = '\0';
913
914             /* I wanted to use cvs-serv/PID, but then you have to worry about
915              * the permissions on the cvs-serv directory being right.  So
916              * use cvs-servPID.
917              */
918             strcat (server_temp_dir, "/cvs-serv");
919
920             p = server_temp_dir + strlen (server_temp_dir);
921             sprintf (p, "%ld", (long) getpid ());
922
923             orig_server_temp_dir = server_temp_dir;
924
925             /* Create the temporary directory, and set the mode to
926              * 700, to discourage random people from tampering with
927              * it.
928              */
929             while ((status = mkdir_p (server_temp_dir)) == EEXIST)
930             {
931                 static const char suffix[] = "abcdefghijklmnopqrstuvwxyz";
932
933                 if (i >= sizeof suffix - 1) break;
934                 if (i == 0) p = server_temp_dir + strlen (server_temp_dir);
935                 p[0] = suffix[i++];
936                 p[1] = '\0';
937             }
938             if (status)
939             {
940                 if (alloc_pending (80 + strlen (server_temp_dir)))
941                     sprintf (pending_error_text,
942                             "E can't create temporary directory %s",
943                             server_temp_dir);
944                 pending_error = status;
945             }
946 #ifndef CHMOD_BROKEN
947             else if (chmod (server_temp_dir, S_IRWXU) < 0)
948             {
949                 int save_errno = errno;
950                 if (alloc_pending (80 + strlen (server_temp_dir)))
951                     sprintf (pending_error_text,
952 "E cannot change permissions on temporary directory %s",
953                              server_temp_dir);
954                 pending_error = save_errno;
955             }
956 #endif
957             else if (CVS_CHDIR (server_temp_dir) < 0)
958             {
959                 int save_errno = errno;
960                 if (alloc_pending (80 + strlen (server_temp_dir)))
961                     sprintf (pending_error_text,
962 "E cannot change to temporary directory %s",
963                              server_temp_dir);
964                 pending_error = save_errno;
965             }
966         }
967     }
968
969     /* Now that we have a config, verify our compression level.  Since 
970      * most clients do not send Gzip-stream requests until after the root
971      * request, wait until the first request following Root to verify that
972      * compression is being used when level 0 is not allowed.
973      */
974     if (gzip_level)
975     {
976         bool forced = false;
977
978         if (gzip_level < config->MinCompressionLevel)
979         {
980             gzip_level = config->MinCompressionLevel;
981             forced = true;
982         }
983
984         if (gzip_level > config->MaxCompressionLevel)
985         {
986             gzip_level = config->MaxCompressionLevel;
987             forced = true;
988         }
989
990         if (forced && !quiet
991             && alloc_pending_warning (120 + strlen (program_name)))
992             sprintf (pending_warning_text,
993 "E %s server: Forcing compression level %d (allowed: %d <= z <= %d).",
994                      program_name, gzip_level, config->MinCompressionLevel,
995                      config->MaxCompressionLevel);
996     }
997
998     path = xmalloc (strlen (current_parsed_root->directory)
999                    + sizeof (CVSROOTADM)
1000                    + 2);
1001     if (path == NULL)
1002     {
1003         pending_error = ENOMEM;
1004         return;
1005     }
1006     (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM);
1007     if (!isaccessible (path, R_OK | X_OK))
1008     {
1009         int save_errno = errno;
1010         if (alloc_pending (80 + strlen (path)))
1011             sprintf (pending_error_text, "E Cannot access %s", path);
1012         pending_error = save_errno;
1013     }
1014     free (path);
1015
1016     setenv (CVSROOT_ENV, current_parsed_root->directory, 1);
1017 }
1018
1019
1020
1021 static int max_dotdot_limit = 0;
1022
1023 /* Is this pathname OK to recurse into when we are running as the server?
1024    If not, call error() with a fatal error.  */
1025 void
1026 server_pathname_check (char *path)
1027 {
1028     TRACE (TRACE_FUNCTION, "server_pathname_check (%s)",
1029            path ? path : "(null)");
1030
1031     /* An absolute pathname is almost surely a path on the *client* machine,
1032        and is unlikely to do us any good here.  It also is probably capable
1033        of being a security hole in the anonymous readonly case.  */
1034     if (ISABSOLUTE (path))
1035         /* Giving an error is actually kind of a cop-out, in the sense
1036            that it would be nice for "cvs co -d /foo/bar/baz" to work.
1037            A quick fix in the server would be requiring Max-dotdot of
1038            at least one if pathnames are absolute, and then putting
1039            /abs/foo/bar/baz in the temp dir beside the /d/d/d stuff.
1040            A cleaner fix in the server might be to decouple the
1041            pathnames we pass back to the client from pathnames in our
1042            temp directory (this would also probably remove the need
1043            for Max-dotdot).  A fix in the client would have the client
1044            turn it into "cd /foo/bar; cvs co -d baz" (more or less).
1045            This probably has some problems with pathnames which appear
1046            in messages.  */
1047         error ( 1, 0,
1048                 "absolute pathnames invalid for server (specified `%s')",
1049                 path );
1050     if (pathname_levels (path) > max_dotdot_limit)
1051     {
1052         /* Similar to the ISABSOLUTE case in security implications.  */
1053         error (0, 0, "protocol error: `%s' contains more leading ..", path);
1054         error (1, 0, "than the %d which Max-dotdot specified",
1055                max_dotdot_limit);
1056     }
1057 }
1058
1059
1060
1061 /* Is file or directory REPOS an absolute pathname within the
1062    current_parsed_root->directory?  If yes, return 0.  If no, set pending_error
1063    and return 1.  */
1064 static int
1065 outside_root (char *repos)
1066 {
1067     size_t repos_len = strlen (repos);
1068     size_t root_len = strlen (current_parsed_root->directory);
1069
1070     /* ISABSOLUTE (repos) should always be true, but
1071        this is a good security precaution regardless. -DRP
1072      */
1073     if (!ISABSOLUTE (repos))
1074     {
1075         if (alloc_pending (repos_len + 80))
1076             sprintf (pending_error_text, "\
1077 E protocol error: %s is not absolute", repos);
1078         return 1;
1079     }
1080
1081     if (repos_len < root_len
1082         || strncmp (current_parsed_root->directory, repos, root_len) != 0)
1083     {
1084     not_within:
1085         if (alloc_pending (strlen (current_parsed_root->directory)
1086                            + strlen (repos)
1087                            + 80))
1088             sprintf (pending_error_text, "\
1089 E protocol error: directory '%s' not within root '%s'",
1090                      repos, current_parsed_root->directory);
1091         return 1;
1092     }
1093     if (repos_len > root_len)
1094     {
1095         if (repos[root_len] != '/')
1096             goto not_within;
1097         if (pathname_levels (repos + root_len + 1) > 0)
1098             goto not_within;
1099     }
1100     return 0;
1101 }
1102
1103
1104
1105 /* Is file or directory FILE outside the current directory (that is, does
1106    it contain '/')?  If no, return 0.  If yes, set pending_error
1107    and return 1.  */
1108 static int
1109 outside_dir (char *file)
1110 {
1111     if (strchr (file, '/') != NULL)
1112     {
1113         if (alloc_pending (strlen (file)
1114                            + 80))
1115             sprintf (pending_error_text, "\
1116 E protocol error: directory '%s' not within current directory",
1117                      file);
1118         return 1;
1119     }
1120     return 0;
1121 }
1122
1123
1124
1125 /*
1126  * Add as many directories to the temp directory as the client tells us it
1127  * will use "..", so we never try to access something outside the temp
1128  * directory via "..".
1129  */
1130 static void
1131 serve_max_dotdot (char *arg)
1132 {
1133     int lim = atoi (arg);
1134     int i;
1135     char *p;
1136
1137 #ifdef PROXY_SUPPORT
1138     if (proxy_log) return;
1139 #endif /* PROXY_SUPPORT */
1140
1141     if (lim < 0 || lim > 10000)
1142         return;
1143     p = xmalloc (strlen (server_temp_dir) + 2 * lim + 10);
1144     if (p == NULL)
1145     {
1146         pending_error = ENOMEM;
1147         return;
1148     }
1149     strcpy (p, server_temp_dir);
1150     for (i = 0; i < lim; ++i)
1151         strcat (p, "/d");
1152     if (server_temp_dir != orig_server_temp_dir)
1153         free (server_temp_dir);
1154     server_temp_dir = p;
1155     max_dotdot_limit = lim;
1156 }
1157
1158
1159
1160 static char *gDirname;
1161 static char *gupdate_dir;
1162
1163 static void
1164 dirswitch (char *dir, char *repos)
1165 {
1166     int status;
1167     FILE *f;
1168     size_t dir_len;
1169
1170     TRACE (TRACE_FUNCTION, "dirswitch (%s, %s)", dir ? dir : "(null)",
1171            repos ? repos : "(null)");
1172
1173     server_write_entries ();
1174
1175     if (error_pending()) return;
1176
1177     /* Check for bad directory name.
1178
1179        FIXME: could/should unify these checks with server_pathname_check
1180        except they need to report errors differently.  */
1181     if (ISABSOLUTE (dir))
1182     {
1183         if (alloc_pending (80 + strlen (dir)))
1184             sprintf ( pending_error_text,
1185                       "E absolute pathnames invalid for server (specified `%s')",
1186                       dir);
1187         return;
1188     }
1189     if (pathname_levels (dir) > max_dotdot_limit)
1190     {
1191         if (alloc_pending (80 + strlen (dir)))
1192             sprintf (pending_error_text,
1193                      "E protocol error: `%s' has too many ..", dir);
1194         return;
1195     }
1196
1197     dir_len = strlen (dir);
1198
1199     /* Check for a trailing '/'.  This is not ISSLASH because \ in the
1200        protocol is an ordinary character, not a directory separator (of
1201        course, it is perhaps unwise to use it in directory names, but that
1202        is another issue).  */
1203     if (dir_len > 0
1204         && dir[dir_len - 1] == '/')
1205     {
1206         if (alloc_pending (80 + dir_len))
1207             sprintf (pending_error_text,
1208                      "E protocol error: invalid directory syntax in %s", dir);
1209         return;
1210     }
1211
1212     if (gDirname != NULL)
1213         free (gDirname);
1214     if (gupdate_dir != NULL)
1215         free (gupdate_dir);
1216
1217     if (!strcmp (dir, "."))
1218         gupdate_dir = xstrdup ("");
1219     else
1220         gupdate_dir = xstrdup (dir);
1221
1222     gDirname = xmalloc (strlen (server_temp_dir) + dir_len + 40);
1223     if (gDirname == NULL)
1224     {
1225         pending_error = ENOMEM;
1226         return;
1227     }
1228
1229     strcpy (gDirname, server_temp_dir);
1230     strcat (gDirname, "/");
1231     strcat (gDirname, dir);
1232
1233     status = mkdir_p (gDirname);
1234     if (status != 0
1235         && status != EEXIST)
1236     {
1237         if (alloc_pending (80 + strlen (gDirname)))
1238             sprintf (pending_error_text, "E cannot mkdir %s", gDirname);
1239         pending_error = status;
1240         return;
1241     }
1242
1243     /* We need to create adm directories in all path elements because
1244        we want the server to descend them, even if the client hasn't
1245        sent the appropriate "Argument xxx" command to match the
1246        already-sent "Directory xxx" command.  See recurse.c
1247        (start_recursion) for a big discussion of this.  */
1248
1249     status = create_adm_p (server_temp_dir, dir);
1250     if (status != 0)
1251     {
1252         if (alloc_pending (80 + strlen (gDirname)))
1253             sprintf (pending_error_text, "E cannot create_adm_p %s", gDirname);
1254         pending_error = status;
1255         return;
1256     }
1257
1258     if ( CVS_CHDIR (gDirname) < 0)
1259     {
1260         int save_errno = errno;
1261         if (alloc_pending (80 + strlen (gDirname)))
1262             sprintf (pending_error_text, "E cannot change to %s", gDirname);
1263         pending_error = save_errno;
1264         return;
1265     }
1266     /*
1267      * This is pretty much like calling Create_Admin, but Create_Admin doesn't
1268      * report errors in the right way for us.
1269      */
1270     if ((CVS_MKDIR (CVSADM, 0777) < 0) && (errno != EEXIST))
1271     {
1272         int save_errno = errno;
1273         if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM)))
1274             sprintf (pending_error_text,
1275                      "E cannot mkdir %s/%s", gDirname, CVSADM);
1276         pending_error = save_errno;
1277         return;
1278     }
1279
1280     /* The following will overwrite the contents of CVSADM_REP.  This
1281        is the correct behavior -- mkdir_p may have written a
1282        placeholder value to this file and we need to insert the
1283        correct value. */
1284
1285     f = CVS_FOPEN (CVSADM_REP, "w");
1286     if (f == NULL)
1287     {
1288         int save_errno = errno;
1289         if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1290             sprintf (pending_error_text,
1291                      "E cannot open %s/%s", gDirname, CVSADM_REP);
1292         pending_error = save_errno;
1293         return;
1294     }
1295     if (fprintf (f, "%s", repos) < 0)
1296     {
1297         int save_errno = errno;
1298         if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1299             sprintf (pending_error_text,
1300                      "E error writing %s/%s", gDirname, CVSADM_REP);
1301         pending_error = save_errno;
1302         fclose (f);
1303         return;
1304     }
1305     /* Non-remote CVS handles a module representing the entire tree
1306        (e.g., an entry like ``world -a .'') by putting /. at the end
1307        of the Repository file, so we do the same.  */
1308     if (strcmp (dir, ".") == 0
1309         && current_parsed_root != NULL
1310         && current_parsed_root->directory != NULL
1311         && strcmp (current_parsed_root->directory, repos) == 0)
1312     {
1313         if (fprintf (f, "/.") < 0)
1314         {
1315             int save_errno = errno;
1316             if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1317                 sprintf (pending_error_text,
1318                          "E error writing %s/%s", gDirname, CVSADM_REP);
1319             pending_error = save_errno;
1320             fclose (f);
1321             return;
1322         }
1323     }
1324     if (fprintf (f, "\n") < 0)
1325     {
1326         int save_errno = errno;
1327         if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1328             sprintf (pending_error_text,
1329                      "E error writing %s/%s", gDirname, CVSADM_REP);
1330         pending_error = save_errno;
1331         fclose (f);
1332         return;
1333     }
1334     if (fclose (f) == EOF)
1335     {
1336         int save_errno = errno;
1337         if (alloc_pending (80 + strlen (gDirname) + strlen (CVSADM_REP)))
1338             sprintf (pending_error_text,
1339                      "E error closing %s/%s", gDirname, CVSADM_REP);
1340         pending_error = save_errno;
1341         return;
1342     }
1343     /* We open in append mode because we don't want to clobber an
1344        existing Entries file.  */
1345     f = CVS_FOPEN (CVSADM_ENT, "a");
1346     if (f == NULL)
1347     {
1348         int save_errno = errno;
1349         if (alloc_pending (80 + strlen (CVSADM_ENT)))
1350             sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
1351         pending_error = save_errno;
1352         return;
1353     }
1354     if (fclose (f) == EOF)
1355     {
1356         int save_errno = errno;
1357         if (alloc_pending (80 + strlen (CVSADM_ENT)))
1358             sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
1359         pending_error = save_errno;
1360         return;
1361     }
1362 }
1363
1364
1365
1366 static void
1367 serve_repository (char *arg)
1368 {
1369 # ifdef PROXY_SUPPORT
1370     assert (!proxy_log);
1371 # endif /* PROXY_SUPPORT */
1372
1373     if (alloc_pending (80))
1374         strcpy (pending_error_text,
1375                 "E Repository request is obsolete; aborted");
1376     return;
1377 }
1378
1379
1380
1381 static void
1382 serve_directory (char *arg)
1383 {
1384     int status;
1385     char *repos;
1386
1387     TRACE (TRACE_FUNCTION, "serve_directory (%s)", arg ? arg : "(null)");
1388
1389
1390     /* The data needs to be read into the secondary log regardless, but
1391      * processing of anything other than errors is skipped until later.
1392      */
1393     status = buf_read_line (buf_from_net, &repos, NULL);
1394     if (status == 0)
1395     {
1396         if (!ISABSOLUTE (repos))
1397         {
1398             /* Make absolute.
1399              *
1400              * FIXME: This is kinda hacky - we should probably only ever store
1401              * and pass SHORT_REPOS (perhaps with the occassional exception
1402              * for optimizations, but many, many functions end up
1403              * deconstructing REPOS to gain SHORT_REPOS anyhow) - the
1404              * CVSROOT portion of REPOS is redundant with
1405              * current_parsed_root->directory - but since this is the way
1406              * things have always been done, changing this will likely involve
1407              * a major overhaul.
1408              */
1409             char *short_repos;
1410
1411             short_repos = repos;
1412             repos = Xasprintf ("%s/%s",
1413                               current_parsed_root->directory, short_repos);
1414             free (short_repos);
1415         }
1416         else
1417             repos = xstrdup (primary_root_translate (repos));
1418
1419         if (
1420 # ifdef PROXY_SUPPORT
1421             !proxy_log &&
1422 # endif /* PROXY_SUPPORT */
1423             !outside_root (repos))
1424             dirswitch (arg, repos);
1425         free (repos);
1426     }
1427     else if (status == -2)
1428     {
1429         pending_error = ENOMEM;
1430     }
1431     else if (status != 0)
1432     {
1433         pending_error_text = xmalloc (80 + strlen (arg));
1434         if (pending_error_text == NULL)
1435         {
1436             pending_error = ENOMEM;
1437         }
1438         else if (status == -1)
1439         {
1440             sprintf (pending_error_text,
1441                      "E end of file reading mode for %s", arg);
1442         }
1443         else
1444         {
1445             sprintf (pending_error_text,
1446                      "E error reading mode for %s", arg);
1447             pending_error = status;
1448         }
1449     }
1450 }
1451
1452
1453
1454 static void
1455 serve_static_directory (char *arg)
1456 {
1457     FILE *f;
1458
1459     if (error_pending ()
1460 # ifdef PROXY_SUPPORT
1461         || proxy_log
1462 # endif /* PROXY_SUPPORT */
1463        ) return;
1464
1465     f = CVS_FOPEN (CVSADM_ENTSTAT, "w+");
1466     if (f == NULL)
1467     {
1468         int save_errno = errno;
1469         if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
1470             sprintf (pending_error_text, "E cannot open %s", CVSADM_ENTSTAT);
1471         pending_error = save_errno;
1472         return;
1473     }
1474     if (fclose (f) == EOF)
1475     {
1476         int save_errno = errno;
1477         if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
1478             sprintf (pending_error_text, "E cannot close %s", CVSADM_ENTSTAT);
1479         pending_error = save_errno;
1480         return;
1481     }
1482 }
1483
1484
1485
1486 static void
1487 serve_sticky (char *arg)
1488 {
1489     FILE *f;
1490
1491     if (error_pending ()
1492 # ifdef PROXY_SUPPORT
1493         || proxy_log
1494 # endif /* PROXY_SUPPORT */
1495        ) return;
1496
1497     f = CVS_FOPEN (CVSADM_TAG, "w+");
1498     if (f == NULL)
1499     {
1500         int save_errno = errno;
1501         if (alloc_pending (80 + strlen (CVSADM_TAG)))
1502             sprintf (pending_error_text, "E cannot open %s", CVSADM_TAG);
1503         pending_error = save_errno;
1504         return;
1505     }
1506     if (fprintf (f, "%s\n", arg) < 0)
1507     {
1508         int save_errno = errno;
1509         if (alloc_pending (80 + strlen (CVSADM_TAG)))
1510             sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG);
1511         pending_error = save_errno;
1512         return;
1513     }
1514     if (fclose (f) == EOF)
1515     {
1516         int save_errno = errno;
1517         if (alloc_pending (80 + strlen (CVSADM_TAG)))
1518             sprintf (pending_error_text, "E cannot close %s", CVSADM_TAG);
1519         pending_error = save_errno;
1520         return;
1521     }
1522 }
1523
1524
1525
1526 /*
1527  * Read SIZE bytes from buf_from_net, write them to FILE.
1528  *
1529  * Currently this isn't really used for receiving parts of a file --
1530  * the file is still sent over in one chunk.  But if/when we get
1531  * spiffy in-process gzip support working, perhaps the compressed
1532  * pieces could be sent over as they're ready, if the network is fast
1533  * enough.  Or something.
1534  */
1535 static void
1536 receive_partial_file (size_t size, int file)
1537 {
1538     while (size > 0)
1539     {
1540         int status;
1541         size_t nread;
1542         char *data;
1543
1544         status = buf_read_data (buf_from_net, size, &data, &nread);
1545         if (status != 0)
1546         {
1547             if (status == -2)
1548                 pending_error = ENOMEM;
1549             else
1550             {
1551                 pending_error_text = xmalloc (80);
1552                 if (pending_error_text == NULL)
1553                     pending_error = ENOMEM;
1554                 else if (status == -1)
1555                 {
1556                     sprintf (pending_error_text,
1557                              "E premature end of file from client");
1558                     pending_error = 0;
1559                 }
1560                 else
1561                 {
1562                     sprintf (pending_error_text,
1563                              "E error reading from client");
1564                     pending_error = status;
1565                 }
1566             }
1567             return;
1568         }
1569
1570         size -= nread;
1571
1572         while (nread > 0)
1573         {
1574             ssize_t nwrote;
1575
1576             nwrote = write (file, data, nread);
1577             if (nwrote < 0)
1578             {
1579                 int save_errno = errno;
1580                 if (alloc_pending (40))
1581                     strcpy (pending_error_text, "E unable to write");
1582                 pending_error = save_errno;
1583
1584                 /* Read and discard the file data.  */
1585                 while (size > 0)
1586                 {
1587                     int status;
1588                     size_t nread;
1589                     char *data;
1590
1591                     status = buf_read_data (buf_from_net, size, &data, &nread);
1592                     if (status != 0)
1593                         return;
1594                     size -= nread;
1595                 }
1596
1597                 return;
1598             }
1599             nread -= nwrote;
1600             data += nwrote;
1601         }
1602     }
1603 }
1604
1605
1606
1607 /* Receive SIZE bytes, write to filename FILE.  */
1608 static void
1609 receive_file (size_t size, char *file, int gzipped)
1610 {
1611     int fd;
1612     char *arg = file;
1613
1614     /* Write the file.  */
1615     fd = CVS_OPEN (arg, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1616     if (fd < 0)
1617     {
1618         int save_errno = errno;
1619         if (alloc_pending (40 + strlen (arg)))
1620             sprintf (pending_error_text, "E cannot open %s", arg);
1621         pending_error = save_errno;
1622         return;
1623     }
1624
1625     if (gzipped)
1626     {
1627         /* Using gunzip_and_write isn't really a high-performance
1628            approach, because it keeps the whole thing in memory
1629            (contiguous memory, worse yet).  But it seems easier to
1630            code than the alternative (and less vulnerable to subtle
1631            bugs).  Given that this feature is mainly for
1632            compatibility, that is the better tradeoff.  */
1633
1634         size_t toread = size;
1635         char *filebuf;
1636         char *p;
1637
1638         filebuf = xmalloc (size);
1639         p = filebuf;
1640         /* If NULL, we still want to read the data and discard it.  */
1641
1642         while (toread > 0)
1643         {
1644             int status;
1645             size_t nread;
1646             char *data;
1647
1648             status = buf_read_data (buf_from_net, toread, &data, &nread);
1649             if (status != 0)
1650             {
1651                 if (status == -2)
1652                     pending_error = ENOMEM;
1653                 else
1654                 {
1655                     pending_error_text = xmalloc (80);
1656                     if (pending_error_text == NULL)
1657                         pending_error = ENOMEM;
1658                     else if (status == -1)
1659                     {
1660                         sprintf (pending_error_text,
1661                                  "E premature end of file from client");
1662                         pending_error = 0;
1663                     }
1664                     else
1665                     {
1666                         sprintf (pending_error_text,
1667                                  "E error reading from client");
1668                         pending_error = status;
1669                     }
1670                 }
1671                 return;
1672             }
1673
1674             toread -= nread;
1675
1676             if (filebuf != NULL)
1677             {
1678                 memcpy (p, data, nread);
1679                 p += nread;
1680             }
1681         }
1682         if (filebuf == NULL)
1683         {
1684             pending_error = ENOMEM;
1685             goto out;
1686         }
1687
1688         if (gunzip_and_write (fd, file, (unsigned char *) filebuf, size))
1689         {
1690             if (alloc_pending (80))
1691                 sprintf (pending_error_text,
1692                          "E aborting due to compression error");
1693         }
1694         free (filebuf);
1695     }
1696     else
1697         receive_partial_file (size, fd);
1698
1699     if (pending_error_text)
1700     {
1701         char *p = xrealloc (pending_error_text,
1702                            strlen (pending_error_text) + strlen (arg) + 30);
1703         if (p)
1704         {
1705             pending_error_text = p;
1706             sprintf (p + strlen (p), ", file %s", arg);
1707         }
1708         /* else original string is supposed to be unchanged */
1709     }
1710
1711  out:
1712     if (close (fd) < 0 && !error_pending ())
1713     {
1714         int save_errno = errno;
1715         if (alloc_pending (40 + strlen (arg)))
1716             sprintf (pending_error_text, "E cannot close %s", arg);
1717         pending_error = save_errno;
1718         return;
1719     }
1720 }
1721
1722
1723
1724 /* Kopt for the next file sent in Modified or Is-modified.  */
1725 static char *kopt;
1726
1727 /* Timestamp (Checkin-time) for next file sent in Modified or
1728    Is-modified.  */
1729 static int checkin_time_valid;
1730 static time_t checkin_time;
1731
1732
1733
1734 /*
1735  * Used to keep track of Entry requests.
1736  */
1737 struct an_entry {
1738     struct an_entry *next;
1739     char *entry;
1740 };
1741
1742 static struct an_entry *entries;
1743
1744 static void
1745 serve_is_modified (char *arg)
1746 {
1747     struct an_entry *p;
1748     char *name;
1749     char *cp;
1750     char *timefield;
1751     /* Have we found this file in "entries" yet.  */
1752     int found;
1753
1754     if (error_pending ()
1755 # ifdef PROXY_SUPPORT
1756         || proxy_log
1757 # endif /* PROXY_SUPPORT */
1758        ) return;
1759
1760     if (outside_dir (arg))
1761         return;
1762
1763     /* Rewrite entries file to have `M' in timestamp field.  */
1764     found = 0;
1765     for (p = entries; p != NULL; p = p->next)
1766     {
1767         name = p->entry + 1;
1768         cp = strchr (name, '/');
1769         if (cp != NULL
1770             && strlen (arg) == cp - name
1771             && strncmp (arg, name, cp - name) == 0)
1772         {
1773             if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
1774             {
1775                 /* We didn't find the record separator or it is followed by
1776                  * the end of the string, so just exit.
1777                  */
1778                 if (alloc_pending (80))
1779                     sprintf (pending_error_text,
1780                              "E Malformed Entry encountered.");
1781                 return;
1782             }
1783             /* If the time field is not currently empty, then one of
1784              * serve_modified, serve_is_modified, & serve_unchanged were
1785              * already called for this file.  We would like to ignore the
1786              * reinvocation silently or, better yet, exit with an error
1787              * message, but we just avoid the copy-forward and overwrite the
1788              * value from the last invocation instead.  See the comment below
1789              * for more.
1790              */
1791             if (*timefield == '/')
1792             {
1793                 /* Copy forward one character.  Space was allocated for this
1794                  * already in serve_entry().  */
1795                 cp = timefield + strlen (timefield);
1796                 cp[1] = '\0';
1797                 while (cp > timefield)
1798                 {
1799                     *cp = cp[-1];
1800                     --cp;
1801                 }
1802
1803                 /* *timefield == '/';  */
1804             }
1805             /* If *TIMEFIELD wasn't '/' and wasn't '+', we assume that it was
1806              * because of multiple calls to Is-modified & Unchanged by the
1807              * client and just overwrite the value from the last call.
1808              * Technically, we should probably either ignore calls after the
1809              * first or send the client an error, since the client/server
1810              * protocol specification specifies that only one call to either
1811              * Is-Modified or Unchanged is allowed, but broken versions of
1812              * CVSNT (at least 2.0.34 - 2.0.41, reported fixed in 2.0.41a) and
1813              * the WinCVS & TortoiseCVS clients which depend on those broken
1814              * versions of CVSNT (WinCVS 1.3 & at least one TortoiseCVS
1815              * release) rely on this behavior.
1816              */
1817             if (*timefield != '+')
1818                 *timefield = 'M';
1819
1820             if (kopt != NULL)
1821             {
1822                 if (alloc_pending (strlen (name) + 80))
1823                     sprintf (pending_error_text,
1824                              "E protocol error: both Kopt and Entry for %s",
1825                              arg);
1826                 free (kopt);
1827                 kopt = NULL;
1828                 return;
1829             }
1830             found = 1;
1831             break;
1832         }
1833     }
1834     if (!found)
1835     {
1836         /* We got Is-modified but no Entry.  Add a dummy entry.
1837            The "D" timestamp is what makes it a dummy.  */
1838         p = xmalloc (sizeof (struct an_entry));
1839         if (p == NULL)
1840         {
1841             pending_error = ENOMEM;
1842             return;
1843         }
1844         p->entry = xmalloc (strlen (arg) + 80);
1845         if (p->entry == NULL)
1846         {
1847             pending_error = ENOMEM;
1848             free (p);
1849             return;
1850         }
1851         strcpy (p->entry, "/");
1852         strcat (p->entry, arg);
1853         strcat (p->entry, "//D/");
1854         if (kopt != NULL)
1855         {
1856             strcat (p->entry, kopt);
1857             free (kopt);
1858             kopt = NULL;
1859         }
1860         strcat (p->entry, "/");
1861         p->next = entries;
1862         entries = p;
1863     }
1864 }
1865
1866
1867
1868 static void
1869 serve_modified (char *arg)
1870 {
1871     size_t size;
1872     int read_size;
1873     int status;
1874     char *size_text;
1875     char *mode_text;
1876
1877     int gzipped = 0;
1878
1879     /*
1880      * This used to return immediately if error_pending () was true.
1881      * However, that fails, because it causes each line of the file to
1882      * be echoed back to the client as an unrecognized command.  The
1883      * client isn't reading from the socket, so eventually both
1884      * processes block trying to write to the other.  Now, we try to
1885      * read the file if we can.
1886      */
1887
1888     status = buf_read_line (buf_from_net, &mode_text, NULL);
1889     if (status != 0)
1890     {
1891         if (status == -2)
1892             pending_error = ENOMEM;
1893         else
1894         {
1895             pending_error_text = xmalloc (80 + strlen (arg));
1896             if (pending_error_text == NULL)
1897                 pending_error = ENOMEM;
1898             else
1899             {
1900                 if (status == -1)
1901                     sprintf (pending_error_text,
1902                              "E end of file reading mode for %s", arg);
1903                 else
1904                 {
1905                     sprintf (pending_error_text,
1906                              "E error reading mode for %s", arg);
1907                     pending_error = status;
1908                 }
1909             }
1910         }
1911         return;
1912     }
1913
1914     status = buf_read_line (buf_from_net, &size_text, NULL);
1915     if (status != 0)
1916     {
1917         if (status == -2)
1918             pending_error = ENOMEM;
1919         else
1920         {
1921             pending_error_text = xmalloc (80 + strlen (arg));
1922             if (pending_error_text == NULL)
1923                 pending_error = ENOMEM;
1924             else
1925             {
1926                 if (status == -1)
1927                     sprintf (pending_error_text,
1928                              "E end of file reading size for %s", arg);
1929                 else
1930                 {
1931                     sprintf (pending_error_text,
1932                              "E error reading size for %s", arg);
1933                     pending_error = status;
1934                 }
1935             }
1936         }
1937         free (mode_text);
1938         return;
1939     }
1940     if (size_text[0] == 'z')
1941     {
1942         gzipped = 1;
1943         read_size = atoi (size_text + 1);
1944     }
1945     else
1946         read_size = atoi (size_text);
1947     free (size_text);
1948
1949     if (read_size < 0 && alloc_pending (80))
1950     {
1951         sprintf (pending_error_text,
1952                  "E client sent invalid (negative) file size");
1953         return;
1954     }
1955     else
1956         size = read_size;
1957
1958     if (error_pending ())
1959     {
1960         /* Now that we know the size, read and discard the file data.  */
1961         while (size > 0)
1962         {
1963             int status;
1964             size_t nread;
1965             char *data;
1966
1967             status = buf_read_data (buf_from_net, size, &data, &nread);
1968             if (status != 0)
1969                 return;
1970             size -= nread;
1971         }
1972         free (mode_text);
1973         return;
1974     }
1975
1976     if (
1977 # ifdef PROXY_SUPPORT
1978         !proxy_log &&
1979 # endif /* PROXY_SUPPORT */
1980         outside_dir (arg))
1981     {
1982         free (mode_text);
1983         return;
1984     }
1985
1986     receive_file (size,
1987 # ifdef PROXY_SUPPORT
1988                   proxy_log ? DEVNULL :
1989 # endif /* PROXY_SUPPORT */
1990                               arg,
1991                   gzipped);
1992     if (error_pending ())
1993     {
1994         free (mode_text);
1995         return;
1996     }
1997
1998 # ifdef PROXY_SUPPORT
1999     /* We've read all the data that needed to be read if we're still logging
2000      * for a secondary.  Return.
2001      */
2002     if (proxy_log) return;
2003 # endif /* PROXY_SUPPORT */
2004
2005     if (checkin_time_valid)
2006     {
2007         struct utimbuf t;
2008
2009         memset (&t, 0, sizeof (t));
2010         t.modtime = t.actime = checkin_time;
2011         if (utime (arg, &t) < 0)
2012         {
2013             int save_errno = errno;
2014             if (alloc_pending (80 + strlen (arg)))
2015                 sprintf (pending_error_text, "E cannot utime %s", arg);
2016             pending_error = save_errno;
2017             free (mode_text);
2018             return;
2019         }
2020         checkin_time_valid = 0;
2021     }
2022
2023     {
2024         int status = change_mode (arg, mode_text, 0);
2025         free (mode_text);
2026         if (status)
2027         {
2028             if (alloc_pending (40 + strlen (arg)))
2029                 sprintf (pending_error_text,
2030                          "E cannot change mode for %s", arg);
2031             pending_error = status;
2032             return;
2033         }
2034     }
2035
2036     /* Make sure that the Entries indicate the right kopt.  We probably
2037        could do this even in the non-kopt case and, I think, save a stat()
2038        call in time_stamp_server.  But for conservatism I'm leaving the
2039        non-kopt case alone.  */
2040     if (kopt != NULL)
2041         serve_is_modified (arg);
2042 }
2043
2044
2045
2046 static void
2047 serve_enable_unchanged (char *arg)
2048 {
2049 # ifdef PROXY_SUPPORT
2050     /* Might as well skip this since this function does nothing anyhow.  If
2051      * it did do anything and could generate errors, then the line below would
2052      * be necessary since this can be processed before a `Root' request.
2053      *
2054      *     if (reprocessing) return;
2055      */
2056 # endif /* PROXY_SUPPORT */
2057 }
2058
2059
2060
2061 static void
2062 serve_unchanged (char *arg)
2063 {
2064     struct an_entry *p;
2065     char *name;
2066     char *cp;
2067     char *timefield;
2068
2069     if (error_pending ()
2070 # ifdef PROXY_SUPPORT
2071         || proxy_log
2072 # endif /* PROXY_SUPPORT */
2073        ) return;
2074
2075     if (outside_dir (arg))
2076         return;
2077
2078     /* Rewrite entries file to have `=' in timestamp field.  */
2079     for (p = entries; p != NULL; p = p->next)
2080     {
2081         name = p->entry + 1;
2082         cp = strchr (name, '/');
2083         if (cp != NULL
2084             && strlen (arg) == cp - name
2085             && strncmp (arg, name, cp - name) == 0)
2086         {
2087             if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
2088             {
2089                 /* We didn't find the record separator or it is followed by
2090                  * the end of the string, so just exit.
2091                  */
2092                 if (alloc_pending (80))
2093                     sprintf (pending_error_text,
2094                              "E Malformed Entry encountered.");
2095                 return;
2096             }
2097             /* If the time field is not currently empty, then one of
2098              * serve_modified, serve_is_modified, & serve_unchanged were
2099              * already called for this file.  We would like to ignore the
2100              * reinvocation silently or, better yet, exit with an error
2101              * message, but we just avoid the copy-forward and overwrite the
2102              * value from the last invocation instead.  See the comment below
2103              * for more.
2104              */
2105             if (*timefield == '/')
2106             {
2107                 /* Copy forward one character.  Space was allocated for this
2108                  * already in serve_entry().  */
2109                 cp = timefield + strlen (timefield);
2110                 cp[1] = '\0';
2111                 while (cp > timefield)
2112                 {
2113                     *cp = cp[-1];
2114                     --cp;
2115                 }
2116
2117                 /* *timefield == '/';  */
2118             }
2119             if (*timefield != '+')
2120             {
2121                 /* '+' is a conflict marker and we don't want to mess with it
2122                  * until Version_TS catches it.
2123                  */
2124                 if (timefield[1] != '/')
2125                 {
2126                     /* Obliterate anything else in TIMEFIELD.  This is again to
2127                      * support the broken CVSNT clients mentioned below, in
2128                      * conjunction with strict timestamp string boundry
2129                      * checking in time_stamp_server() from vers_ts.c &
2130                      * file_has_conflict() from subr.c, since the broken
2131                      * clients used to send malformed timestamp fields in the
2132                      * Entry request that they then depended on the subsequent
2133                      * Unchanged request to overwrite.
2134                      */
2135                     char *d = timefield + 1;
2136                     if ((cp = strchr (d, '/')))
2137                     {
2138                         while (*cp)
2139                         {
2140                             *d++ = *cp++;
2141                         }
2142                         *d = '\0';
2143                     }
2144                 }
2145                 /* If *TIMEFIELD wasn't '/', we assume that it was because of
2146                  * multiple calls to Is-modified & Unchanged by the client and
2147                  * just overwrite the value from the last call.  Technically,
2148                  * we should probably either ignore calls after the first or
2149                  * send the client an error, since the client/server protocol
2150                  * specification specifies that only one call to either
2151                  * Is-Modified or Unchanged is allowed, but broken versions of
2152                  * CVSNT (at least 2.0.34 - 2.0.41, reported fixed in 2.0.41a)
2153                  * and the WinCVS & TortoiseCVS clients which depend on those
2154                  * broken versions of CVSNT (WinCVS 1.3 & at least one
2155                  * TortoiseCVS release) rely on this behavior.
2156                  */
2157                 *timefield = '=';
2158             }
2159             break;
2160         }
2161     }
2162 }
2163
2164
2165
2166 static void
2167 serve_entry (char *arg)
2168 {
2169     struct an_entry *p;
2170     char *cp;
2171     int i = 0;
2172
2173     if (error_pending()
2174 # ifdef PROXY_SUPPORT
2175         || proxy_log
2176 # endif /* PROXY_SUPPORT */
2177        ) return;
2178
2179     /* Verify that the entry is well-formed.  This can avoid problems later.
2180      * At the moment we only check that the Entry contains five slashes in
2181      * approximately the correct locations since some of the code makes
2182      * assumptions about this.
2183      */
2184     cp = arg;
2185     if (*cp == 'D') cp++;
2186     while (i++ < 5)
2187     {
2188         if (!cp || *cp != '/')
2189         {
2190             if (alloc_pending (80))
2191                 sprintf (pending_error_text,
2192                          "E protocol error: Malformed Entry");
2193             return;
2194         }
2195         cp = strchr (cp + 1, '/');
2196     }
2197
2198     p = xmalloc (sizeof (struct an_entry));
2199     if (p == NULL)
2200     {
2201         pending_error = ENOMEM;
2202         return;
2203     }
2204     /* Leave space for serve_unchanged to write '=' if it wants.  */
2205     cp = xmalloc (strlen (arg) + 2);
2206     if (cp == NULL)
2207     {
2208         free (p);
2209         pending_error = ENOMEM;
2210         return;
2211     }
2212     strcpy (cp, arg);
2213     p->next = entries;
2214     p->entry = cp;
2215     entries = p;
2216 }
2217
2218
2219
2220 static void
2221 serve_kopt (char *arg)
2222 {
2223     if (error_pending ()
2224 # ifdef PROXY_SUPPORT
2225         || proxy_log
2226 # endif /* PROXY_SUPPORT */
2227        )
2228         return;
2229
2230     if (kopt != NULL)
2231     {
2232         if (alloc_pending (80 + strlen (arg)))
2233             sprintf (pending_error_text,
2234                      "E protocol error: duplicate Kopt request: %s", arg);
2235         return;
2236     }
2237
2238     /* Do some sanity checks.  In particular, that it is not too long.
2239        This lets the rest of the code not worry so much about buffer
2240        overrun attacks.  Probably should call RCS_check_kflag here,
2241        but that would mean changing RCS_check_kflag to handle errors
2242        other than via exit(), fprintf(), and such.  */
2243     if (strlen (arg) > 10)
2244     {
2245         if (alloc_pending (80 + strlen (arg)))
2246             sprintf (pending_error_text,
2247                      "E protocol error: invalid Kopt request: %s", arg);
2248         return;
2249     }
2250
2251     kopt = xmalloc (strlen (arg) + 1);
2252     if (kopt == NULL)
2253     {
2254         pending_error = ENOMEM;
2255         return;
2256     }
2257     strcpy (kopt, arg);
2258 }
2259
2260
2261
2262 static void
2263 serve_checkin_time (char *arg)
2264 {
2265     struct timespec t;
2266
2267     if (error_pending ()
2268 # ifdef PROXY_SUPPORT
2269         || proxy_log
2270 # endif /* PROXY_SUPPORT */
2271        )
2272         return;
2273
2274     if (checkin_time_valid)
2275     {
2276         if (alloc_pending (80 + strlen (arg)))
2277             sprintf (pending_error_text,
2278                      "E protocol error: duplicate Checkin-time request: %s",
2279                      arg);
2280         return;
2281     }
2282
2283     if (!get_date (&t, arg, NULL))
2284     {
2285         if (alloc_pending (80 + strlen (arg)))
2286             sprintf (pending_error_text, "E cannot parse date %s", arg);
2287         return;
2288     }
2289
2290     /* Truncate any nanoseconds returned by get_date().  */
2291     checkin_time = t.tv_sec;
2292     checkin_time_valid = 1;
2293 }
2294
2295
2296
2297 static void
2298 server_write_entries (void)
2299 {
2300     FILE *f;
2301     struct an_entry *p;
2302     struct an_entry *q;
2303
2304     if (entries == NULL)
2305         return;
2306
2307     f = NULL;
2308     /* Note that we free all the entries regardless of errors.  */
2309     if (!error_pending ())
2310     {
2311         /* We open in append mode because we don't want to clobber an
2312            existing Entries file.  If we are checking out a module
2313            which explicitly lists more than one file in a particular
2314            directory, then we will wind up calling
2315            server_write_entries for each such file.  */
2316         f = CVS_FOPEN (CVSADM_ENT, "a");
2317         if (f == NULL)
2318         {
2319             int save_errno = errno;
2320             if (alloc_pending (80 + strlen (CVSADM_ENT)))
2321                 sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
2322             pending_error = save_errno;
2323         }
2324     }
2325     for (p = entries; p != NULL;)
2326     {
2327         if (!error_pending ())
2328         {
2329             if (fprintf (f, "%s\n", p->entry) < 0)
2330             {
2331                 int save_errno = errno;
2332                 if (alloc_pending (80 + strlen(CVSADM_ENT)))
2333                     sprintf (pending_error_text,
2334                              "E cannot write to %s", CVSADM_ENT);
2335                 pending_error = save_errno;
2336             }
2337         }
2338         free (p->entry);
2339         q = p->next;
2340         free (p);
2341         p = q;
2342     }
2343     entries = NULL;
2344     if (f != NULL && fclose (f) == EOF && !error_pending ())
2345     {
2346         int save_errno = errno;
2347         if (alloc_pending (80 + strlen (CVSADM_ENT)))
2348             sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
2349         pending_error = save_errno;
2350     }
2351 }
2352
2353
2354
2355 # ifdef PROXY_SUPPORT
2356 /*
2357  * callback proc to run a script when admin finishes.
2358  */
2359 static int
2360 prepost_proxy_proc (const char *repository, const char *filter, void *closure)
2361 {
2362     char *cmdline;
2363     bool *pre = closure;
2364
2365     /* %c = cvs_cmd_name
2366      * %I = commit ID
2367      * %p = shortrepos
2368      * %r = repository
2369      */
2370     TRACE (TRACE_FUNCTION, "prepost_proxy_proc (%s, %s, %s)", repository,
2371            filter, *pre ? "pre" : "post");
2372
2373     /*
2374      * Cast any NULL arguments as appropriate pointers as this is an
2375      * stdarg function and we need to be certain the caller gets what
2376      * is expected.
2377      */
2378     cmdline = format_cmdline (
2379 # ifdef SUPPORT_OLD_INFO_FMT_STRINGS
2380                               0, ".",
2381 # endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
2382                               filter,
2383                               "c", "s", cvs_cmd_name,
2384                               "I", "s", global_session_id,
2385                               "R", "s", referrer ? referrer->original : "NONE",
2386                               "p", "s", ".",
2387                               "r", "s", current_parsed_root->directory,
2388                               "P", "s", config->PrimaryServer->original,
2389                               (char *) NULL);
2390
2391     if (!cmdline || !strlen (cmdline))
2392     {
2393         if (cmdline) free (cmdline);
2394         if (*pre)
2395             error (0, 0, "preadmin proc resolved to the empty string!");
2396         else
2397             error (0, 0, "postadmin proc resolved to the empty string!");
2398         return 1;
2399     }
2400
2401     run_setup (cmdline);
2402
2403     free (cmdline);
2404
2405     /* FIXME - read the comment in verifymsg_proc() about why we use abs()
2406      * below() and shouldn't.
2407      */
2408     return abs (run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
2409                           RUN_NORMAL | RUN_SIGIGNORE));
2410 }
2411
2412
2413
2414 /* Become a secondary write proxy to a master server.
2415  *
2416  * This function opens the connection to the primary, dumps the secondary log
2417  * to the primary, then reads data from any available connection and writes it
2418  * to its partner:
2419  *
2420  *   buf_from_net -> buf_to_primary
2421  *   buf_from_primary -> buf_to_net
2422  *
2423  * When all "from" connections have sent EOF and all data has been sent to
2424  * "to" connections, this function closes the "to" pipes and returns.
2425  */
2426 static void
2427 become_proxy (void)
2428 {
2429     struct buffer *buf_to_primary;
2430     struct buffer *buf_from_primary;
2431
2432     /* Close the client log and open it for read.  */
2433     struct buffer *buf_clientlog = log_buffer_rewind (proxy_log_out);
2434     int status, to_primary_fd, from_primary_fd, to_net_fd, from_net_fd;
2435
2436     /* Call presecondary script.  */
2437     bool pre = true;
2438
2439             char *data;
2440             size_t thispass, got;
2441             int s;
2442             char *newdata;
2443
2444     Parse_Info (CVSROOTADM_PREPROXY, current_parsed_root->directory,
2445                 prepost_proxy_proc, PIOPT_ALL, &pre);
2446
2447     /* Open connection to primary server.  */
2448     open_connection_to_server (config->PrimaryServer, &buf_to_primary,
2449                                &buf_from_primary);
2450     setup_logfiles ("CVS_SECONDARY_LOG", &buf_to_primary, &buf_from_primary);
2451     if ((status = set_nonblock (buf_from_primary)))
2452         error (1, status, "failed to set nonblocking io from primary");
2453     if ((status = set_nonblock (buf_from_net)))
2454         error (1, status, "failed to set nonblocking io from client");
2455     if ((status = set_nonblock (buf_to_primary)))
2456         error (1, status, "failed to set nonblocking io to primary");
2457     if ((status = set_nonblock (buf_to_net)))
2458         error (1, status, "failed to set nonblocking io to client");
2459
2460     to_primary_fd = buf_get_fd (buf_to_primary);
2461     from_primary_fd = buf_get_fd (buf_from_primary);
2462     to_net_fd = buf_get_fd (buf_to_net);
2463     assert (to_primary_fd >= 0 && from_primary_fd >= 0 && to_net_fd >= 0);
2464
2465     /* Close the client log and open it for read.  */
2466     rewind_buf_from_net ();
2467
2468     while (from_primary_fd >= 0 || to_primary_fd >= 0)
2469     {
2470         fd_set readfds, writefds;
2471         int status, numfds = -1;
2472         struct timeval *timeout_ptr;
2473         struct timeval timeout;
2474         size_t toread;
2475
2476         FD_ZERO (&readfds);
2477         FD_ZERO (&writefds);
2478
2479         /* The fd for a multi-source buffer can change with any read.  */
2480         from_net_fd = buf_from_net ? buf_get_fd (buf_from_net) : -1;
2481
2482         if ((buf_from_net && !buf_empty_p (buf_from_net))
2483             || (buf_from_primary && !buf_empty_p (buf_from_primary)))
2484         {
2485             /* There is data pending so don't block if we don't find any new
2486              * data on the fds.
2487              */
2488             timeout.tv_sec = 0;
2489             timeout.tv_usec = 0;
2490             timeout_ptr = &timeout;
2491         }
2492         else
2493             /* block indefinately */
2494             timeout_ptr = NULL;
2495
2496         /* Set writefds if data is pending.  */
2497         if (to_net_fd >= 0 && !buf_empty_p (buf_to_net))
2498         {
2499             FD_SET (to_net_fd, &writefds);
2500             numfds = MAX (numfds, to_net_fd);
2501         }
2502         if (to_primary_fd >= 0 && !buf_empty_p (buf_to_primary))
2503         {
2504             FD_SET (to_primary_fd, &writefds);
2505             numfds = MAX (numfds, to_primary_fd);
2506         }
2507
2508         /* Set readfds if descriptors are still open.  */
2509         if (from_net_fd >= 0)
2510         {
2511             FD_SET (from_net_fd, &readfds);
2512             numfds = MAX (numfds, from_net_fd);
2513         }
2514         if (from_primary_fd >= 0)
2515         {
2516             FD_SET (from_primary_fd, &readfds);
2517             numfds = MAX (numfds, from_primary_fd);
2518         }
2519
2520         /* NUMFDS needs to be the highest descriptor + 1 according to the
2521          * select spec.
2522          */
2523         numfds++;
2524
2525         do {
2526             /* This used to select on exceptions too, but as far
2527                as I know there was never any reason to do that and
2528                SCO doesn't let you select on exceptions on pipes.  */
2529             numfds = select (numfds, &readfds, &writefds,
2530                              NULL, timeout_ptr);
2531             if (numfds < 0 && errno != EINTR)
2532             {
2533                 /* Sending an error to the client, possibly in the middle of a
2534                  * separate protocol message, will likely not mean much to the
2535                  * client, but it's better than nothing, I guess.
2536                  */
2537                 buf_output0 (buf_to_net, "E select failed\n");
2538                 print_error (errno);
2539                 exit (EXIT_FAILURE);
2540             }
2541         } while (numfds < 0);
2542
2543         if (numfds == 0)
2544         {
2545             FD_ZERO (&readfds);
2546             FD_ZERO (&writefds);
2547         }
2548
2549         if (to_net_fd >= 0 && FD_ISSET (to_net_fd, &writefds))
2550         {
2551             /* What should we do with errors?  syslog() them?  */
2552             buf_send_output (buf_to_net);
2553             buf_flush (buf_to_net, false);
2554         }
2555
2556         status = 0;
2557         if (from_net_fd >= 0 && (FD_ISSET (from_net_fd, &readfds)))
2558             status = buf_input_data (buf_from_net, NULL);
2559
2560         if (buf_from_net && !buf_empty_p (buf_from_net))
2561         {
2562             if (buf_to_primary)
2563                 buf_append_buffer (buf_to_primary, buf_from_net);
2564             else
2565                 /* (Sys?)log this?  */;
2566                 
2567         }
2568
2569         if (status == -1 /* EOF */)
2570         {
2571             SIG_beginCrSect();
2572             /* Need only to shut this down and set to NULL, really, in
2573              * crit sec, to ensure no double-dispose and to make sure
2574              * network pipes are closed as properly as possible, but I
2575              * don't see much optimization potential in saving values and
2576              * postponing the free.
2577              */
2578             buf_shutdown (buf_from_net);
2579             buf_free (buf_from_net);
2580             buf_from_net = NULL;
2581             /* So buf_to_primary will be closed at the end of this loop.  */
2582             from_net_fd = -1;
2583             SIG_endCrSect();
2584         }
2585         else if (status > 0 /* ERRNO */)
2586         {
2587             buf_output0 (buf_to_net,
2588                          "E buf_input_data failed reading from client\n");
2589             print_error (status);
2590             exit (EXIT_FAILURE);
2591         }
2592
2593         if (to_primary_fd >= 0 && FD_ISSET (to_primary_fd, &writefds))
2594         {
2595             /* What should we do with errors?  syslog() them?  */
2596             buf_send_output (buf_to_primary);
2597             buf_flush (buf_to_primary, false);
2598         }
2599
2600         status = 0;
2601         if (from_primary_fd >= 0 && FD_ISSET (from_primary_fd, &readfds))
2602             status = buf_input_data (buf_from_primary, &toread);
2603
2604         /* Avoid resending data from the server which we already sent to the
2605          * client.  Otherwise clients get really confused.
2606          */
2607         if (buf_clientlog
2608             && buf_from_primary && !buf_empty_p (buf_from_primary))
2609         {
2610             /* Dispose of data we already sent to the client.  */
2611             while (buf_clientlog && toread > 0)
2612             {
2613                 s = buf_read_data (buf_clientlog, toread, &data, &got);
2614                 if (s == -2)
2615                     error (1, ENOMEM, "Failed to read data.");
2616                 if (s == -1)
2617                 {
2618                     buf_shutdown (buf_clientlog);
2619                     buf_clientlog = NULL;
2620                 }
2621                 else if (s)
2622                     error (1, s, "Error reading writeproxy log.");
2623                 else
2624                 {
2625                     thispass = got;
2626                     while (thispass > 0)
2627                     {
2628                         /* No need to check for errors here since we know we
2629                          * won't read more than buf_input read into
2630                          * BUF_FROM_PRIMARY (see how TOREAD is set above).
2631                          */
2632                         buf_read_data (buf_from_primary, thispass, &newdata,
2633                                        &got);
2634                         /* Verify that we are throwing away what we think we
2635                          * are.
2636                          *
2637                          * It is valid to assume that the secondary and primary
2638                          * are closely enough in sync that this portion of the
2639                          * communication will be in sync beacuse if they were
2640                          * not, then the secondary might provide a
2641                          * valid-request string to the client which contained a
2642                          * request that the primary didn't support.  If the
2643                          * client later used the request, the primary server
2644                          * would exit anyhow.
2645                          *
2646                          * FIXME?
2647                          * An alternative approach might be to make sure that
2648                          * the secondary provides the same string as the
2649                          * primary regardless, for purposes like pointing a
2650                          * secondary at an unwitting primary, in which case it
2651                          * might be useful to have some way to override the
2652                          * valid-requests string on a secondary, but it seems
2653                          * much easier to simply sync the versions, at the
2654                          * moment.
2655                          */
2656                         if (memcmp (data, newdata, got))
2657                             error (1, 0, "Secondary out of sync with primary!");
2658                         data += got;
2659                         thispass -= got;
2660                     }
2661                     toread -= got;
2662                 }
2663             }
2664         }
2665
2666         if (buf_from_primary && !buf_empty_p (buf_from_primary))
2667         {
2668             if (buf_to_net)
2669                 buf_append_buffer (buf_to_net, buf_from_primary);
2670             else
2671                 /* (Sys?)log this?  */;
2672                 
2673         }
2674
2675         if (status == -1 /* EOF */)
2676         {
2677             buf_shutdown (buf_from_primary);
2678             buf_from_primary = NULL;
2679             from_primary_fd = -1;
2680         }
2681         else if (status > 0 /* ERRNO */)
2682         {
2683             buf_output0 (buf_to_net,
2684                          "E buf_input_data failed reading from primary\n");
2685             print_error (status);
2686             exit (EXIT_FAILURE);
2687         }
2688
2689         /* If our "source pipe" is closed and all data has been sent, avoid
2690          * selecting it for writability, but don't actually close the buffer in
2691          * case other routines want to use it later.  The buffer will be closed
2692          * in server_cleanup ().
2693          */
2694         if (from_primary_fd < 0
2695             && buf_to_net && buf_empty_p (buf_to_net))
2696             to_net_fd = -1;
2697
2698         if (buf_to_primary
2699             && (/* Assume that there is no further reason to keep the buffer to
2700                  * the primary open if we can no longer read its responses.
2701                  */
2702                 (from_primary_fd < 0 && buf_to_primary)
2703                 /* Also close buf_to_primary when it becomes impossible to find
2704                  * more data to send to it.  We don't close buf_from_primary
2705                  * yet since there may be data pending or the primary may react
2706                  * to the EOF on its input pipe.
2707                  */
2708                 || (from_net_fd < 0 && buf_empty_p (buf_to_primary))))
2709         {
2710             buf_shutdown (buf_to_primary);
2711             buf_free (buf_to_primary);
2712             buf_to_primary = NULL;
2713
2714             /* Setting the fd < 0 with from_primary_fd already < 0 will cause
2715              * an escape from this while loop.
2716              */
2717             to_primary_fd = -1;
2718         }
2719     }
2720
2721     /* Call postsecondary script.  */
2722     pre = false;
2723     Parse_Info (CVSROOTADM_POSTPROXY, current_parsed_root->directory,
2724                 prepost_proxy_proc, PIOPT_ALL, &pre);
2725 }
2726 # endif /* PROXY_SUPPORT */
2727
2728
2729
2730 struct notify_note {
2731     /* Directory in which this notification happens.  xmalloc'd*/
2732     char *dir;
2733
2734     /* xmalloc'd.  */
2735     char *update_dir;
2736
2737     /* xmalloc'd.  */
2738     char *filename;
2739
2740     /* The following three all in one xmalloc'd block, pointed to by TYPE.
2741        Each '\0' terminated.  */
2742     /* "E" or "U".  */
2743     char *type;
2744     /* time+host+dir */
2745     char *val;
2746     char *watches;
2747
2748     struct notify_note *next;
2749 };
2750
2751 static struct notify_note *notify_list;
2752 /* Used while building list, to point to the last node that already exists.  */
2753 static struct notify_note *last_node;
2754
2755 static void
2756 serve_notify (char *arg)
2757 {
2758     struct notify_note *new = NULL;
2759     char *data = NULL;
2760     int status;
2761
2762     if (error_pending ()) return;
2763
2764     if (isProxyServer())
2765     {
2766 # ifdef PROXY_SUPPORT
2767         if (!proxy_log)
2768         {
2769 # endif /* PROXY_SUPPORT */
2770             if (alloc_pending (160) + strlen (program_name))
2771                 sprintf (pending_error_text, 
2772 "E This CVS server does not support disconnected `%s edit'.  For now, remove all `%s' files in your workspace and try your command again.",
2773                          program_name, CVSADM_NOTIFY);
2774         return;
2775 # ifdef PROXY_SUPPORT
2776         }
2777         else
2778         {
2779             /* This is effectively a write command, so run it on the primary.  */
2780             become_proxy ();
2781             exit (EXIT_SUCCESS);
2782         }
2783 # endif /* PROXY_SUPPORT */
2784     }
2785
2786     if (outside_dir (arg))
2787         return;
2788
2789     if (gDirname == NULL)
2790         goto error;
2791
2792     new = xmalloc (sizeof (struct notify_note));
2793     if (new == NULL)
2794     {
2795         pending_error = ENOMEM;
2796         return;
2797     }
2798     new->dir = xmalloc (strlen (gDirname) + 1);
2799     new->update_dir = xmalloc (strlen (gupdate_dir) + 1);
2800     new->filename = xmalloc (strlen (arg) + 1);
2801     if (new->dir == NULL || new->update_dir == NULL || new->filename == NULL)
2802     {
2803         pending_error = ENOMEM;
2804         if (new->dir != NULL)
2805             free (new->dir);
2806         free (new);
2807         return;
2808     }
2809     strcpy (new->dir, gDirname);
2810     strcpy (new->update_dir, gupdate_dir);
2811     strcpy (new->filename, arg);
2812
2813     status = buf_read_line (buf_from_net, &data, NULL);
2814     if (status != 0)
2815     {
2816         if (status == -2)
2817             pending_error = ENOMEM;
2818         else
2819         {
2820             pending_error_text = xmalloc (80 + strlen (arg));
2821             if (pending_error_text == NULL)
2822                 pending_error = ENOMEM;
2823             else
2824             {
2825                 if (status == -1)
2826                     sprintf (pending_error_text,
2827                              "E end of file reading notification for %s", arg);
2828                 else
2829                 {
2830                     sprintf (pending_error_text,
2831                              "E error reading notification for %s", arg);
2832                     pending_error = status;
2833                 }
2834             }
2835         }
2836         free (new->filename);
2837         free (new->dir);
2838         free (new);
2839     }
2840     else
2841     {
2842         char *cp;
2843
2844         if (!data[0])
2845             goto error;
2846
2847         if (strchr (data, '+'))
2848             goto error;
2849
2850         new->type = data;
2851         if (data[1] != '\t')
2852             goto error;
2853         data[1] = '\0';
2854         cp = data + 2;
2855         new->val = cp;
2856         cp = strchr (cp, '\t');
2857         if (cp == NULL)
2858             goto error;
2859         *cp++ = '+';
2860         cp = strchr (cp, '\t');
2861         if (cp == NULL)
2862             goto error;
2863         *cp++ = '+';
2864         cp = strchr (cp, '\t');
2865         if (cp == NULL)
2866             goto error;
2867         *cp++ = '\0';
2868         new->watches = cp;
2869         /* If there is another tab, ignore everything after it,
2870            for future expansion.  */
2871         cp = strchr (cp, '\t');
2872         if (cp != NULL)
2873             *cp = '\0';
2874
2875         new->next = NULL;
2876
2877         if (last_node == NULL)
2878             notify_list = new;
2879         else
2880             last_node->next = new;
2881         last_node = new;
2882     }
2883     return;
2884   error:
2885     pending_error = 0;
2886     if (alloc_pending (80))
2887         strcpy (pending_error_text,
2888                 "E Protocol error; misformed Notify request");
2889     if (data != NULL)
2890         free (data);
2891     if (new != NULL)
2892     {
2893         free (new->filename);
2894         free (new->update_dir);
2895         free (new->dir);
2896         free (new);
2897     }
2898     return;
2899 }
2900
2901
2902
2903 static void
2904 serve_hostname (char *arg)
2905 {
2906     free (hostname);
2907     hostname = xstrdup (arg);
2908     return;
2909 }
2910
2911
2912
2913 static void
2914 serve_localdir (char *arg)
2915 {
2916     if (CurDir) free (CurDir);
2917     CurDir = xstrdup (arg);
2918 }
2919
2920
2921
2922 /* Process all the Notify requests that we have stored up.  Returns 0
2923    if successful, if not prints error message (via error()) and
2924    returns negative value.  */
2925 static int
2926 server_notify (void)
2927 {
2928     struct notify_note *p;
2929     char *repos;
2930
2931     TRACE (TRACE_FUNCTION, "server_notify()");
2932
2933     while (notify_list != NULL)
2934     {
2935         if (CVS_CHDIR (notify_list->dir) < 0)
2936         {
2937             error (0, errno, "cannot change to %s", notify_list->dir);
2938             return -1;
2939         }
2940         repos = Name_Repository (NULL, NULL);
2941
2942         lock_dir_for_write (repos);
2943
2944         fileattr_startdir (repos);
2945
2946         notify_do (*notify_list->type, notify_list->filename,
2947                    notify_list->update_dir, getcaller(), notify_list->val,
2948                    notify_list->watches, repos);
2949
2950         buf_output0 (buf_to_net, "Notified ");
2951         {
2952             char *dir = notify_list->dir + strlen (server_temp_dir) + 1;
2953             if (dir[0] == '\0')
2954                 buf_append_char (buf_to_net, '.');
2955             else
2956                 buf_output0 (buf_to_net, dir);
2957             buf_append_char (buf_to_net, '/');
2958             buf_append_char (buf_to_net, '\n');
2959         }
2960         buf_output0 (buf_to_net, repos);
2961         buf_append_char (buf_to_net, '/');
2962         buf_output0 (buf_to_net, notify_list->filename);
2963         buf_append_char (buf_to_net, '\n');
2964         free (repos);
2965
2966         p = notify_list->next;
2967         free (notify_list->filename);
2968         free (notify_list->dir);
2969         free (notify_list->type);
2970         free (notify_list);
2971         notify_list = p;
2972
2973         fileattr_write ();
2974         fileattr_free ();
2975
2976         Lock_Cleanup ();
2977     }
2978
2979     last_node = NULL;
2980
2981     /* The code used to call fflush (stdout) here, but that is no
2982        longer necessary.  The data is now buffered in buf_to_net,
2983        which will be flushed by the caller, do_cvs_command.  */
2984
2985     return 0;
2986 }
2987
2988
2989
2990 /* This request is processed in all passes since requests which must
2991  * sometimes be processed before it is known whether we are running as a
2992  * secondary or not, for instance the `expand-modules' request, sometimes use
2993  * the `Arguments'.
2994  */
2995 static void
2996 serve_argument (char *arg)
2997 {
2998     char *p;
2999
3000     if (error_pending()) return;
3001
3002     if (argument_count >= 10000)
3003     {
3004         if (alloc_pending (80))
3005             sprintf (pending_error_text, 
3006                      "E Protocol error: too many arguments");
3007         return;
3008     }
3009
3010     if (argument_vector_size <= argument_count)
3011     {
3012         argument_vector_size *= 2;
3013         argument_vector = xnrealloc (argument_vector,
3014                                      argument_vector_size, sizeof (char *));
3015         if (argument_vector == NULL)
3016         {
3017             pending_error = ENOMEM;
3018             return;
3019         }
3020     }
3021     p = xmalloc (strlen (arg) + 1);
3022     if (p == NULL)
3023     {
3024         pending_error = ENOMEM;
3025         return;
3026     }
3027     strcpy (p, arg);
3028     argument_vector[argument_count++] = p;
3029 }
3030
3031
3032
3033 /* For secondary servers, this is handled in all passes, as is the `Argument'
3034  * request, and for the same reasons.
3035  */
3036 static void
3037 serve_argumentx (char *arg)
3038 {
3039     char *p;
3040
3041     if (error_pending()) return;
3042     
3043     if (argument_count <= 1) 
3044     {
3045         if (alloc_pending (80))
3046             sprintf (pending_error_text,
3047 "E Protocol error: called argumentx without prior call to argument");
3048         return;
3049     }
3050
3051     p = argument_vector[argument_count - 1];
3052     p = xrealloc (p, strlen (p) + 1 + strlen (arg) + 1);
3053     if (p == NULL)
3054     {
3055         pending_error = ENOMEM;
3056         return;
3057     }
3058     strcat (p, "\n");
3059     strcat (p, arg);
3060     argument_vector[argument_count - 1] = p;
3061 }
3062
3063
3064
3065 static void
3066 serve_global_option (char *arg)
3067 {
3068 # ifdef PROXY_SUPPORT
3069     /* This can generate error messages and termination before `Root' requests,
3070      * so it must be dealt with in the first pass.
3071      */ 
3072     if (reprocessing) return;
3073 # endif /* PROXY_SUPPORT */
3074
3075     if (arg[0] != '-' || arg[1] == '\0' || arg[2] != '\0')
3076     {
3077     error_return:
3078         if (alloc_pending (strlen (arg) + 80))
3079             sprintf (pending_error_text,
3080                      "E Protocol error: bad global option %s",
3081                      arg);
3082         return;
3083     }
3084     switch (arg[1])
3085     {
3086         case 'l':
3087             error(0, 0, "WARNING: global `-l' option ignored.");
3088             break;
3089         case 'n':
3090             noexec = 1;
3091             logoff = 1;
3092             break;
3093         case 'q':
3094             quiet = 1;
3095             break;
3096         case 'r':
3097             cvswrite = 0;
3098             break;
3099         case 'Q':
3100             really_quiet = 1;
3101             break;
3102         case 't':
3103             trace++;
3104             break;
3105         default:
3106             goto error_return;
3107     }
3108 }
3109
3110
3111
3112 /* This needs to be processed before Root requests, so we allow it to be
3113  * be processed before knowing whether we are running as a secondary server
3114  * to allow `noop' and `Root' requests to generate errors as before.
3115  */
3116 static void
3117 serve_set (char *arg)
3118 {
3119 # ifdef PROXY_SUPPORT
3120     if (reprocessing) return;
3121 # endif /* PROXY_SUPPORT */
3122
3123     /* FIXME: This sends errors immediately (I think); they should be
3124        put into pending_error.  */
3125     variable_set (arg);
3126 }
3127
3128 # ifdef ENCRYPTION
3129
3130 #   ifdef HAVE_KERBEROS
3131
3132 static void
3133 serve_kerberos_encrypt( char *arg )
3134 {
3135 #     ifdef PROXY_SUPPORT
3136     assert (!proxy_log);
3137 #     endif /* PROXY_SUPPORT */
3138
3139     /* All future communication with the client will be encrypted.  */
3140
3141     buf_to_net = krb_encrypt_buffer_initialize (buf_to_net, 0, sched,
3142                                                 kblock,
3143                                                 buf_to_net->memory_error);
3144     buf_from_net = krb_encrypt_buffer_initialize (buf_from_net, 1, sched,
3145                                                   kblock,
3146                                                   buf_from_net->memory_error);
3147 }
3148
3149 #   endif /* HAVE_KERBEROS */
3150
3151 #   ifdef HAVE_GSSAPI
3152
3153 static void
3154 serve_gssapi_encrypt( char *arg )
3155 {
3156 #     ifdef PROXY_SUPPORT
3157     assert (!proxy_log);
3158 #     endif /* PROXY_SUPPORT */
3159
3160     if (cvs_gssapi_wrapping)
3161     {
3162         /* We're already using a gssapi_wrap buffer for stream
3163            authentication.  Flush everything we've output so far, and
3164            turn on encryption for future data.  On the input side, we
3165            should only have unwrapped as far as the Gssapi-encrypt
3166            command, so future unwrapping will become encrypted.  */
3167         buf_flush (buf_to_net, 1);
3168         cvs_gssapi_encrypt = 1;
3169         return;
3170     }
3171
3172     /* All future communication with the client will be encrypted.  */
3173
3174     cvs_gssapi_encrypt = 1;
3175
3176     buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
3177                                                     gcontext,
3178                                                     buf_to_net->memory_error);
3179     buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
3180                                                       gcontext,
3181                                                       buf_from_net->memory_error);
3182
3183     cvs_gssapi_wrapping = 1;
3184 }
3185
3186 #   endif /* HAVE_GSSAPI */
3187
3188 # endif /* ENCRYPTION */
3189
3190 # ifdef HAVE_GSSAPI
3191
3192 static void
3193 serve_gssapi_authenticate (char *arg)
3194 {
3195 #   ifdef PROXY_SUPPORT
3196     assert (!proxy_log);
3197 #   endif /* PROXY_SUPPORT */
3198
3199     if (cvs_gssapi_wrapping)
3200     {
3201         /* We're already using a gssapi_wrap buffer for encryption.
3202            That includes authentication, so we don't have to do
3203            anything further.  */
3204         return;
3205     }
3206
3207     buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
3208                                                     gcontext,
3209                                                     buf_to_net->memory_error);
3210     buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
3211                                                       gcontext,
3212                                                       buf_from_net->memory_error);
3213
3214     cvs_gssapi_wrapping = 1;
3215 }
3216
3217 # endif /* HAVE_GSSAPI */
3218
3219
3220
3221 # ifdef SERVER_FLOWCONTROL
3222 /* The maximum we'll queue to the remote client before blocking.  */
3223 #   ifndef SERVER_HI_WATER
3224 #     define SERVER_HI_WATER (2 * 1024 * 1024)
3225 #   endif /* SERVER_HI_WATER */
3226 /* When the buffer drops to this, we restart the child */
3227 #   ifndef SERVER_LO_WATER
3228 #     define SERVER_LO_WATER (1 * 1024 * 1024)
3229 #   endif /* SERVER_LO_WATER */
3230 # endif /* SERVER_FLOWCONTROL */
3231
3232
3233
3234 static void
3235 serve_questionable (char *arg)
3236 {
3237     static int initted;
3238
3239 # ifdef PROXY_SUPPORT
3240     if (proxy_log) return;
3241 # endif /* PROXY_SUPPORT */
3242
3243     if (error_pending ()) return;
3244
3245     if (!initted)
3246     {
3247         /* Pick up ignores from CVSROOTADM_IGNORE, $HOME/.cvsignore on server,
3248            and CVSIGNORE on server.  */
3249         ign_setup ();
3250         initted = 1;
3251     }
3252
3253     if (gDirname == NULL)
3254     {
3255         if (alloc_pending (80))
3256             sprintf (pending_error_text,
3257 "E Protocol error: `Directory' missing");
3258         return;
3259     }
3260
3261     if (outside_dir (arg))
3262         return;
3263
3264     if (!ign_name (arg))
3265     {
3266         char *update_dir;
3267
3268         buf_output (buf_to_net, "M ? ", 4);
3269         update_dir = gDirname + strlen (server_temp_dir) + 1;
3270         if (!(update_dir[0] == '.' && update_dir[1] == '\0'))
3271         {
3272             buf_output0 (buf_to_net, update_dir);
3273             buf_output (buf_to_net, "/", 1);
3274         }
3275         buf_output0 (buf_to_net, arg);
3276         buf_output (buf_to_net, "\n", 1);
3277     }
3278 }
3279
3280
3281
3282 static struct buffer *protocol = NULL;
3283
3284 /* This is the output which we are saving up to send to the server, in the
3285    child process.  We will push it through, via the `protocol' buffer, when
3286    we have a complete line.  */
3287 static struct buffer *saved_output;
3288
3289 /* Likewise, but stuff which will go to stderr.  */
3290 static struct buffer *saved_outerr;
3291
3292
3293
3294 static void
3295 protocol_memory_error (struct buffer *buf)
3296 {
3297     error (1, ENOMEM, "Virtual memory exhausted");
3298 }
3299
3300
3301
3302 /* If command is valid, return 1.
3303  * Else if command is invalid and croak_on_invalid is set, then die.
3304  * Else just return 0 to indicate that command is invalid.
3305  */
3306 static bool
3307 check_command_valid_p (char *cmd_name)
3308 {
3309     /* Right now, only pserver notices invalid commands -- namely,
3310      * write attempts by a read-only user.  Therefore, if CVS_Username
3311      * is not set, this just returns 1, because CVS_Username unset
3312      * means pserver is not active.
3313      */
3314 # ifdef AUTH_SERVER_SUPPORT
3315     if (CVS_Username == NULL)
3316         return true;
3317
3318     if (lookup_command_attribute (cmd_name) & CVS_CMD_MODIFIES_REPOSITORY)
3319     {
3320         /* This command has the potential to modify the repository, so
3321          * we check if the user have permission to do that.
3322          *
3323          * (Only relevant for remote users -- local users can do
3324          * whatever normal Unix file permissions allow them to do.)
3325          *
3326          * The decision method:
3327          *
3328          *    If $CVSROOT/CVSADMROOT_READERS exists and user is listed
3329          *    in it, then read-only access for user.
3330          *
3331          *    Or if $CVSROOT/CVSADMROOT_WRITERS exists and user NOT
3332          *    listed in it, then also read-only access for user.
3333          *
3334          *    Else read-write access for user.
3335          */
3336
3337          char *linebuf = NULL;
3338          int num_red = 0;
3339          size_t linebuf_len = 0;
3340          char *fname;
3341          size_t flen;
3342          FILE *fp;
3343          int found_it = 0;
3344
3345          /* else */
3346          flen = strlen (current_parsed_root->directory)
3347                 + strlen (CVSROOTADM)
3348                 + strlen (CVSROOTADM_READERS)
3349                 + 3;
3350
3351          fname = xmalloc (flen);
3352          (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
3353                         CVSROOTADM, CVSROOTADM_READERS);
3354
3355          fp = fopen (fname, "r");
3356
3357          if (fp == NULL)
3358          {
3359              if (!existence_error (errno))
3360              {
3361                  /* Need to deny access, so that attackers can't fool
3362                     us with some sort of denial of service attack.  */
3363                  error (0, errno, "cannot open %s", fname);
3364                  free (fname);
3365                  return false;
3366              }
3367          }
3368          else  /* successfully opened readers file */
3369          {
3370              while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
3371              {
3372                  /* Hmmm, is it worth importing my own readline
3373                     library into CVS?  It takes care of chopping
3374                     leading and trailing whitespace, "#" comments, and
3375                     newlines automatically when so requested.  Would
3376                     save some code here...  -kff */
3377
3378                  /* Chop newline by hand, for strcmp()'s sake. */
3379                  if (num_red > 0 && linebuf[num_red - 1] == '\n')
3380                      linebuf[num_red - 1] = '\0';
3381
3382                  if (strcmp (linebuf, CVS_Username) == 0)
3383                      goto handle_invalid;
3384              }
3385              if (num_red < 0 && !feof (fp))
3386                  error (0, errno, "cannot read %s", fname);
3387
3388              /* If not listed specifically as a reader, then this user
3389                 has write access by default unless writers are also
3390                 specified in a file . */
3391              if (fclose (fp) < 0)
3392                  error (0, errno, "cannot close %s", fname);
3393          }
3394          free (fname);
3395
3396          /* Now check the writers file.  */
3397
3398          flen = strlen (current_parsed_root->directory)
3399                 + strlen (CVSROOTADM)
3400                 + strlen (CVSROOTADM_WRITERS)
3401                 + 3;
3402
3403          fname = xmalloc (flen);
3404          (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
3405                         CVSROOTADM, CVSROOTADM_WRITERS);
3406
3407          fp = fopen (fname, "r");
3408
3409          if (fp == NULL)
3410          {
3411              if (linebuf)
3412                  free (linebuf);
3413              if (existence_error (errno))
3414              {
3415                  /* Writers file does not exist, so everyone is a writer,
3416                     by default.  */
3417                  free (fname);
3418                  return true;
3419              }
3420              else
3421              {
3422                  /* Need to deny access, so that attackers can't fool
3423                     us with some sort of denial of service attack.  */
3424                  error (0, errno, "cannot read %s", fname);
3425                  free (fname);
3426                  return false;
3427              }
3428          }
3429
3430          found_it = 0;
3431          while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
3432          {
3433              /* Chop newline by hand, for strcmp()'s sake. */
3434              if (num_red > 0 && linebuf[num_red - 1] == '\n')
3435                  linebuf[num_red - 1] = '\0';
3436
3437              if (strcmp (linebuf, CVS_Username) == 0)
3438              {
3439                  found_it = 1;
3440                  break;
3441              }
3442          }
3443          if (num_red < 0 && !feof (fp))
3444              error (0, errno, "cannot read %s", fname);
3445
3446          if (found_it)
3447          {
3448              if (fclose (fp) < 0)
3449                  error (0, errno, "cannot close %s", fname);
3450              if (linebuf)
3451                  free (linebuf);
3452              free (fname);
3453              return true;
3454          }
3455          else   /* writers file exists, but this user not listed in it */
3456          {
3457          handle_invalid:
3458              if (fclose (fp) < 0)
3459                  error (0, errno, "cannot close %s", fname);
3460              if (linebuf)
3461                  free (linebuf);
3462              free (fname);
3463              return false;
3464          }
3465     }
3466 # endif /* AUTH_SERVER_SUPPORT */
3467
3468     /* If ever reach end of this function, command must be valid. */
3469     return true;
3470 }
3471
3472
3473
3474 /* Execute COMMAND in a subprocess with the approriate funky things done.  */
3475
3476 static struct fd_set_wrapper { fd_set fds; } command_fds_to_drain;
3477 # ifdef SUNOS_KLUDGE
3478 static int max_command_fd;
3479 # endif
3480
3481 # ifdef SERVER_FLOWCONTROL
3482 static int flowcontrol_pipe[2];
3483 # endif /* SERVER_FLOWCONTROL */
3484
3485
3486
3487 /*
3488  * Set buffer FD to non-blocking I/O.  Returns 0 for success or errno
3489  * code.
3490  */
3491 int
3492 set_nonblock_fd (int fd)
3493 {
3494 # if defined (F_GETFL) && defined (O_NONBLOCK) && defined (F_SETFL)
3495     int flags;
3496
3497     flags = fcntl (fd, F_GETFL, 0);
3498     if (flags < 0)
3499         return errno;
3500     if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0)
3501         return errno;
3502 # endif /* F_GETFL && O_NONBLOCK && F_SETFL */
3503     return 0;
3504 }
3505
3506
3507
3508 static void
3509 do_cvs_command (char *cmd_name, int (*command) (int, char **))
3510 {
3511     /*
3512      * The following file descriptors are set to -1 if that file is not
3513      * currently open.
3514      */
3515
3516     /* Data on these pipes is a series of '\n'-terminated lines.  */
3517     int stdout_pipe[2];
3518     int stderr_pipe[2];
3519
3520     /*
3521      * Data on this pipe is a series of counted (see buf_send_counted)
3522      * packets.  Each packet must be processed atomically (i.e. not
3523      * interleaved with data from stdout_pipe or stderr_pipe).
3524      */
3525     int protocol_pipe[2];
3526
3527     int dev_null_fd = -1;
3528
3529     int errs;
3530
3531     TRACE (TRACE_FUNCTION, "do_cvs_command (%s)", cmd_name);
3532
3533     /* Write proxy logging is always terminated when a command is received.
3534      * Therefore, we wish to avoid reprocessing the command since that would
3535      * cause endless recursion.
3536      */
3537     if ((command != version || current_parsed_root) && isProxyServer())
3538     {
3539 # ifdef PROXY_SUPPORT
3540         if (reprocessing)
3541             /* This must be the second time we've reached this point.
3542              * Done reprocessing.
3543              */
3544             reprocessing = false;
3545         else
3546         {
3547             if (lookup_command_attribute (cmd_name)
3548                     & CVS_CMD_MODIFIES_REPOSITORY)
3549             {
3550                 become_proxy ();
3551                 exit (EXIT_SUCCESS);
3552             }
3553             else if (/* serve_co may have called this already and missing logs
3554                       * should have generated an error in serve_root().
3555                       */
3556                      proxy_log)
3557             {
3558                 /* Set up the log for reprocessing.  */
3559                 rewind_buf_from_net ();
3560                 /* And return to the main loop in server(), where we will now
3561                  * find the logged secondary data and reread it.
3562                  */
3563                 return;
3564             }
3565         }
3566 # else /* !PROXY_SUPPORT */
3567         if (lookup_command_attribute (cmd_name)
3568                     & CVS_CMD_MODIFIES_REPOSITORY
3569             && alloc_pending (120))
3570             sprintf (pending_error_text, 
3571 "E You need a CVS client that supports the `Redirect' response for write requests to this server.");
3572         return;
3573 # endif /* PROXY_SUPPORT */
3574     }
3575
3576     command_pid = -1;
3577     stdout_pipe[0] = -1;
3578     stdout_pipe[1] = -1;
3579     stderr_pipe[0] = -1;
3580     stderr_pipe[1] = -1;
3581     protocol_pipe[0] = -1;
3582     protocol_pipe[1] = -1;
3583
3584     server_write_entries ();
3585
3586     if (print_pending_error ())
3587         goto free_args_and_return;
3588
3589     /* Global `cvs_cmd_name' is probably "server" right now -- only
3590        serve_export() sets it to anything else.  So we will use local
3591        parameter `cmd_name' to determine if this command is valid for
3592        this user.  */
3593     if (!check_command_valid_p (cmd_name))
3594     {
3595         buf_output0 (buf_to_net, "E ");
3596         buf_output0 (buf_to_net, program_name);
3597         buf_output0 (buf_to_net, " [server aborted]: \"");
3598         buf_output0 (buf_to_net, cmd_name);
3599         buf_output0 (buf_to_net,
3600 "\" requires write access to the repository\n\
3601 error  \n");
3602         goto free_args_and_return;
3603     }
3604     cvs_cmd_name = cmd_name;
3605
3606     (void) server_notify ();
3607
3608     /*
3609      * We use a child process which actually does the operation.  This
3610      * is so we can intercept its standard output.  Even if all of CVS
3611      * were written to go to some special routine instead of writing
3612      * to stdout or stderr, we would still need to do the same thing
3613      * for the RCS commands.
3614      */
3615
3616     if (pipe (stdout_pipe) < 0)
3617     {
3618         buf_output0 (buf_to_net, "E pipe failed\n");
3619         print_error (errno);
3620         goto error_exit;
3621     }
3622     if (pipe (stderr_pipe) < 0)
3623     {
3624         buf_output0 (buf_to_net, "E pipe failed\n");
3625         print_error (errno);
3626         goto error_exit;
3627     }
3628     if (pipe (protocol_pipe) < 0)
3629     {
3630         buf_output0 (buf_to_net, "E pipe failed\n");
3631         print_error (errno);
3632         goto error_exit;
3633     }
3634 # ifdef SERVER_FLOWCONTROL
3635     if (pipe (flowcontrol_pipe) < 0)
3636     {
3637         buf_output0 (buf_to_net, "E pipe failed\n");
3638         print_error (errno);
3639         goto error_exit;
3640     }
3641     set_nonblock_fd (flowcontrol_pipe[0]);
3642     set_nonblock_fd (flowcontrol_pipe[1]);
3643 # endif /* SERVER_FLOWCONTROL */
3644
3645     dev_null_fd = CVS_OPEN (DEVNULL, O_RDONLY);
3646     if (dev_null_fd < 0)
3647     {
3648         buf_output0 (buf_to_net, "E open /dev/null failed\n");
3649         print_error (errno);
3650         goto error_exit;
3651     }
3652
3653     /* We shouldn't have any partial lines from cvs_output and
3654        cvs_outerr, but we handle them here in case there is a bug.  */
3655     /* FIXME: appending a newline, rather than using "MT" as we
3656        do in the child process, is probably not really a very good
3657        way to "handle" them.  */
3658     if (! buf_empty_p (saved_output))
3659     {
3660         buf_append_char (saved_output, '\n');
3661         buf_copy_lines (buf_to_net, saved_output, 'M');
3662     }
3663     if (! buf_empty_p (saved_outerr))
3664     {
3665         buf_append_char (saved_outerr, '\n');
3666         buf_copy_lines (buf_to_net, saved_outerr, 'E');
3667     }
3668
3669     /* Flush out any pending data.  */
3670     buf_flush (buf_to_net, 1);
3671
3672     /* Don't use vfork; we're not going to exec().  */
3673     command_pid = fork ();
3674     if (command_pid < 0)
3675     {
3676         buf_output0 (buf_to_net, "E fork failed\n");
3677         print_error (errno);
3678         goto error_exit;
3679     }
3680     if (command_pid == 0)
3681     {
3682         int exitstatus;
3683
3684         /* Since we're in the child, and the parent is going to take
3685            care of packaging up our error messages, we can clear this
3686            flag.  */
3687         error_use_protocol = 0;
3688
3689         protocol = fd_buffer_initialize (protocol_pipe[1], 0, NULL, false,
3690                                          protocol_memory_error);
3691
3692         /* At this point we should no longer be using buf_to_net and
3693            buf_from_net.  Instead, everything should go through
3694            protocol.  */
3695         if (buf_to_net != NULL)
3696         {
3697             buf_free (buf_to_net);
3698             buf_to_net = NULL;
3699         }
3700         if (buf_from_net != NULL)
3701         {
3702             buf_free (buf_from_net);
3703             buf_from_net = NULL;
3704         }
3705
3706         /* These were originally set up to use outbuf_memory_error.
3707            Since we're now in the child, we should use the simpler
3708            protocol_memory_error function.  */
3709         saved_output->memory_error = protocol_memory_error;
3710         saved_outerr->memory_error = protocol_memory_error;
3711
3712         if (dup2 (dev_null_fd, STDIN_FILENO) < 0)
3713             error (1, errno, "can't set up pipes");
3714         if (dup2 (stdout_pipe[1], STDOUT_FILENO) < 0)
3715             error (1, errno, "can't set up pipes");
3716         if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
3717             error (1, errno, "can't set up pipes");
3718         close (dev_null_fd);
3719         close (stdout_pipe[0]);
3720         close (stdout_pipe[1]);
3721         close (stderr_pipe[0]);
3722         close (stderr_pipe[1]);
3723         close (protocol_pipe[0]);
3724         close_on_exec (protocol_pipe[1]);
3725 # ifdef SERVER_FLOWCONTROL
3726         close_on_exec (flowcontrol_pipe[0]);
3727         close (flowcontrol_pipe[1]);
3728 # endif /* SERVER_FLOWCONTROL */
3729
3730         /*
3731          * Set this in .bashrc if you want to give yourself time to attach
3732          * to the subprocess with a debugger.
3733          */
3734         if (getenv ("CVS_SERVER_SLEEP"))
3735         {
3736             int secs = atoi (getenv ("CVS_SERVER_SLEEP"));
3737             TRACE (TRACE_DATA, "Sleeping CVS_SERVER_SLEEP (%d) seconds", secs);
3738             sleep (secs);
3739         }
3740         else
3741             TRACE (TRACE_DATA, "CVS_SERVER_SLEEP not set.");
3742
3743         exitstatus = (*command) (argument_count, argument_vector);
3744
3745         /* Output any partial lines.  If the client doesn't support
3746            "MT", we go ahead and just tack on a newline since the
3747            protocol doesn't support anything better.  */
3748         if (! buf_empty_p (saved_output))
3749         {
3750             buf_output0 (protocol, supported_response ("MT") ? "MT text " : "M ");
3751             buf_append_buffer (protocol, saved_output);
3752             buf_output (protocol, "\n", 1);
3753             buf_send_counted (protocol);
3754         }
3755         /* For now we just discard partial lines on stderr.  I suspect
3756            that CVS can't write such lines unless there is a bug.  */
3757
3758         buf_free (protocol);
3759
3760         /* Close the pipes explicitly in order to send an EOF to the parent,
3761          * then wait for the parent to close the flow control pipe.  This
3762          * avoids a race condition where a child which dumped more than the
3763          * high water mark into the pipes could complete its job and exit,
3764          * leaving the parent process to attempt to write a stop byte to the
3765          * closed flow control pipe, which earned the parent a SIGPIPE, which
3766          * it normally only expects on the network pipe and that causes it to
3767          * exit with an error message, rather than the SIGCHILD that it knows
3768          * how to handle correctly.
3769          */
3770         /* Let exit() close STDIN - it's from /dev/null anyhow.  */
3771         fclose (stderr);
3772         fclose (stdout);
3773         close (protocol_pipe[1]);
3774 # ifdef SERVER_FLOWCONTROL
3775         {
3776             char junk;
3777             ssize_t status;
3778             while ((status = read (flowcontrol_pipe[0], &junk, 1)) > 0
3779                    || (status == -1 && errno == EAGAIN));
3780         }
3781         /* FIXME: No point in printing an error message with error(),
3782          * as STDERR is already closed, but perhaps this could be syslogged?
3783          */
3784 # endif
3785
3786         exit (exitstatus);
3787     }
3788
3789     /* OK, sit around getting all the input from the child.  */
3790     {
3791         struct buffer *stdoutbuf;
3792         struct buffer *stderrbuf;
3793         struct buffer *protocol_inbuf;
3794         /* Number of file descriptors to check in select ().  */
3795         int num_to_check;
3796         int count_needed = 1;
3797 # ifdef SERVER_FLOWCONTROL
3798         int have_flowcontrolled = 0;
3799 # endif /* SERVER_FLOWCONTROL */
3800
3801         FD_ZERO (&command_fds_to_drain.fds);
3802         num_to_check = stdout_pipe[0];
3803         FD_SET (stdout_pipe[0], &command_fds_to_drain.fds);
3804         num_to_check = MAX (num_to_check, stderr_pipe[0]);
3805         FD_SET (stderr_pipe[0], &command_fds_to_drain.fds);
3806         num_to_check = MAX (num_to_check, protocol_pipe[0]);
3807         FD_SET (protocol_pipe[0], &command_fds_to_drain.fds);
3808         num_to_check = MAX (num_to_check, STDOUT_FILENO);
3809 # ifdef SUNOS_KLUDGE
3810         max_command_fd = num_to_check;
3811 # endif
3812         /*
3813          * File descriptors are numbered from 0, so num_to_check needs to
3814          * be one larger than the largest descriptor.
3815          */
3816         ++num_to_check;
3817         if (num_to_check > FD_SETSIZE)
3818         {
3819             buf_output0 (buf_to_net,
3820                          "E internal error: FD_SETSIZE not big enough.\n\
3821 error  \n");
3822             goto error_exit;
3823         }
3824
3825         stdoutbuf = fd_buffer_initialize (stdout_pipe[0], 0, NULL, true,
3826                                           input_memory_error);
3827
3828         stderrbuf = fd_buffer_initialize (stderr_pipe[0], 0, NULL, true,
3829                                           input_memory_error);
3830
3831         protocol_inbuf = fd_buffer_initialize (protocol_pipe[0], 0, NULL, true,
3832                                                input_memory_error);
3833
3834         set_nonblock (buf_to_net);
3835         set_nonblock (stdoutbuf);
3836         set_nonblock (stderrbuf);
3837         set_nonblock (protocol_inbuf);
3838
3839         if (close (stdout_pipe[1]) < 0)
3840         {
3841             buf_output0 (buf_to_net, "E close failed\n");
3842             print_error (errno);
3843             goto error_exit;
3844         }
3845         stdout_pipe[1] = -1;
3846
3847         if (close (stderr_pipe[1]) < 0)
3848         {
3849             buf_output0 (buf_to_net, "E close failed\n");
3850             print_error (errno);
3851             goto error_exit;
3852         }
3853         stderr_pipe[1] = -1;
3854
3855         if (close (protocol_pipe[1]) < 0)
3856         {
3857             buf_output0 (buf_to_net, "E close failed\n");
3858             print_error (errno);
3859             goto error_exit;
3860         }
3861         protocol_pipe[1] = -1;
3862
3863 # ifdef SERVER_FLOWCONTROL
3864         if (close (flowcontrol_pipe[0]) < 0)
3865         {
3866             buf_output0 (buf_to_net, "E close failed\n");
3867             print_error (errno);
3868             goto error_exit;
3869         }
3870         flowcontrol_pipe[0] = -1;
3871 # endif /* SERVER_FLOWCONTROL */
3872
3873         if (close (dev_null_fd) < 0)
3874         {
3875             buf_output0 (buf_to_net, "E close failed\n");
3876             print_error&nb