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