~ubuntu-branches/ubuntu/oneiric/nis/oneiric-proposed

« back to all changes in this revision

Viewing changes to ypserv-2.18/rpc.yppasswdd/yppasswdd.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2005-11-16 23:42:06 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20051116234206-p00omaw5ji5q0qhr
Tags: 3.15-3ubuntu1
Resynchronise with Debian.  (me)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (c) 1996, 1997, 1998, 1999, 2001, 2005 Thorsten Kukuk, <kukuk@suse.de>
 
3
   Copyright (c) 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
 
4
 
 
5
   This file is part of the NYS YP Server.
 
6
 
 
7
   The YP Server is free software; you can redistribute it and/or
 
8
   modify it under the terms of the GNU General Public License
 
9
   version 2 as published by the Free Software Foundation.
 
10
 
 
11
   The NYS YP Server is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
   General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public
 
17
   License along with the NYS YP Server; see the file COPYING.  If
 
18
   not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 
19
   Cambridge, MA 02139, USA. */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include "config.h"
 
23
#endif
 
24
 
 
25
#include <sys/types.h>
 
26
#include <sys/socket.h>
 
27
#include <sys/ioctl.h>
 
28
#include <sys/stat.h>
 
29
#include <sys/wait.h>
 
30
#include <termios.h>
 
31
#include <signal.h>
 
32
#include <unistd.h>
 
33
#include <fcntl.h>
 
34
#include <syslog.h>
 
35
#include <stdio.h>
 
36
#include <stdlib.h>
 
37
#include <string.h>
 
38
#include <errno.h>
 
39
#include <rpc/rpc.h>
 
40
#include <rpc/pmap_clnt.h>
 
41
#if defined(HAVE_RPC_SVC_SOC_H)
 
42
#include <rpc/svc_soc.h>
 
43
#endif
 
44
#include "yppasswd.h"
 
45
#if defined(HAVE_GETOPT_H)
 
46
#include <getopt.h>
 
47
#endif
 
48
 
 
49
#include "log_msg.h"
 
50
#include "compat.h"
 
51
 
 
52
#ifdef HAVE_PATHS_H
 
53
#include <paths.h>
 
54
#endif
 
55
#ifndef _PATH_VARRUN
 
56
#define _PATH_VARRUN "/etc/"
 
57
#endif
 
58
#define _YPPASSWDD_PIDFILE _PATH_VARRUN"yppasswdd.pid"
 
59
 
 
60
int use_shadow = 0;
 
61
int allow_chsh = 0;
 
62
int allow_chfn = 0;
 
63
int solaris_mode = -1;
 
64
int x_flag = -1;
 
65
 
 
66
#define xprt_addr(xprt) (svc_getcaller(xprt)->sin_addr)
 
67
#define xprt_port(xprt) ntohs(svc_getcaller(xprt)->sin_port)
 
68
void yppasswdprog_1 (struct svc_req *rqstp, SVCXPRT * transp);
 
69
void reaper (int sig);
 
70
 
 
71
/*==============================================================*
 
72
 * RPC dispatch function
 
73
 *==============================================================*/
 
74
void
 
75
yppasswdprog_1 (struct svc_req *rqstp, SVCXPRT * transp)
 
76
{
 
77
  yppasswd argument;
 
78
  int *result;
 
79
  xdrproc_t xdr_argument, xdr_result;
 
80
 
 
81
  switch (rqstp->rq_proc)
 
82
    {
 
83
    case NULLPROC:
 
84
      svc_sendreply (transp, (xdrproc_t) xdr_void, (char *) NULL);
 
85
      return;
 
86
 
 
87
    case YPPASSWDPROC_UPDATE:
 
88
      xdr_argument = (xdrproc_t) xdr_yppasswd;
 
89
      xdr_result = (xdrproc_t) xdr_int;
 
90
      break;
 
91
 
 
92
    default:
 
93
      svcerr_noproc (transp);
 
94
      return;
 
95
    }
 
96
  memset ((char *) &argument, 0, sizeof (argument));
 
97
  if (!svc_getargs (transp, xdr_argument, (caddr_t) &argument))
 
98
    {
 
99
      svcerr_decode (transp);
 
100
      return;
 
101
    }
 
102
  result = yppasswdproc_pwupdate_1 (&argument, rqstp);
 
103
  if (result != NULL
 
104
      && !svc_sendreply (transp, (xdrproc_t) xdr_result, (char *)result))
 
105
    {
 
106
      svcerr_systemerr (transp);
 
107
    }
 
108
  if (!svc_freeargs (transp, xdr_argument, (caddr_t) &argument))
 
109
    {
 
110
      log_msg ("unable to free arguments\n");
 
111
      exit (1);
 
112
    }
 
113
}
 
114
 
 
115
/* Create a pidfile on startup */
 
116
static void
 
117
create_pidfile (void)
 
118
{
 
119
  int fd, left, written;
 
120
  pid_t pid;
 
121
  char pbuf[50], *ptr;
 
122
  struct flock lock;
 
123
 
 
124
  fd = open (_YPPASSWDD_PIDFILE, O_CREAT | O_RDWR,
 
125
             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 
126
  if (fd < 0)
 
127
    {
 
128
      log_msg ("cannot create pidfile %s", _YPPASSWDD_PIDFILE);
 
129
      if (debug_flag)
 
130
        log_msg ("\n");
 
131
    }
 
132
 
 
133
  lock.l_type = F_WRLCK;
 
134
  lock.l_start = 0;
 
135
  lock.l_whence = SEEK_SET;
 
136
  lock.l_len = 0;
 
137
 
 
138
  /* Is the pidfile locked by another ypserv ? */
 
139
  if (fcntl (fd, F_GETLK, &lock) < 0)
 
140
    {
 
141
      log_msg ("fcntl error");
 
142
      if (debug_flag)
 
143
        log_msg ("\n");
 
144
    }
 
145
  if (lock.l_type == F_UNLCK)
 
146
    pid = 0;            /* false, region is not locked by another proc */
 
147
  else
 
148
    pid = lock.l_pid;   /* true, return pid of lock owner */
 
149
 
 
150
  if (0 != pid)
 
151
    {
 
152
      log_msg ("rpc.yppasswdd already running (pid %d) - exiting", pid);
 
153
      if (debug_flag)
 
154
        log_msg ("\n");
 
155
      exit (1);
 
156
    }
 
157
 
 
158
  /* write lock */
 
159
  lock.l_type = F_WRLCK;
 
160
  lock.l_start = 0;
 
161
  lock.l_whence = SEEK_SET;
 
162
  lock.l_len = 0;
 
163
  if (0 != fcntl (fd, F_SETLK, &lock))
 
164
    log_msg ("cannot lock pidfile");
 
165
  sprintf (pbuf, "%ld\n", (long) getpid ());
 
166
  left = strlen (pbuf);
 
167
  ptr = pbuf;
 
168
  while (left > 0)
 
169
    {
 
170
      if ((written = write (fd, ptr, left)) <= 0)
 
171
        return;                 /* error */
 
172
      left -= written;
 
173
      ptr += written;
 
174
    }
 
175
  return;
 
176
}
 
177
 
 
178
 
 
179
static void
 
180
usage (FILE * fp, int n)
 
181
{
 
182
  fputs ("Usage: rpc.yppasswdd [--debug] [-s shadowfile] [-p passwdfile] [-e chsh|chfn]\n", fp);
 
183
  fputs ("       rpc.yppasswdd [--debug] [-D directory] [-e chsh|chfn]\n", fp);
 
184
  fputs ("       rpc.yppasswdd [--debug] [-x program |-E program] [-e chsh|chfn]\n", fp);
 
185
  fputs ("       rpc.yppasswdd --port number\n", fp);
 
186
  fputs ("       rpc.yppasswdd --version\n", fp);
 
187
  exit (n);
 
188
}
 
189
 
 
190
static void
 
191
sig_child (int sig UNUSED)
 
192
{
 
193
  int save_errno = errno;
 
194
 
 
195
  while (wait3 (NULL, WNOHANG, NULL) > 0)
 
196
    ;
 
197
  errno = save_errno;
 
198
}
 
199
 
 
200
/* Clean up if we quit the program. */
 
201
static void
 
202
sig_quit (int sig UNUSED)
 
203
{
 
204
  pmap_unset (YPPASSWDPROG, YPPASSWDVERS);
 
205
  unlink (_YPPASSWDD_PIDFILE);
 
206
  exit (0);
 
207
}
 
208
 
 
209
 
 
210
static void
 
211
install_sighandler (void)
 
212
{
 
213
  struct sigaction sa;
 
214
 
 
215
  sigaction (SIGPIPE, NULL, &sa);
 
216
  sa.sa_handler = SIG_IGN;
 
217
#if !defined(sun) || (defined(sun) && defined(__svr4__))
 
218
  sa.sa_flags |= SA_RESTART;
 
219
  /* The opposite to SA_ONESHOT, do  not  restore
 
220
     the  signal  action.  This provides behavior
 
221
     compatible with BSD signal semantics. */
 
222
#endif
 
223
  sigemptyset (&sa.sa_mask);
 
224
  sigaction (SIGPIPE, &sa, NULL);
 
225
  /* Clear up if child exists */
 
226
  sigaction (SIGCHLD, NULL, &sa);
 
227
#if !defined(sun) || (defined(sun) && defined(__svr4__))
 
228
  sa.sa_flags |= SA_RESTART;
 
229
#endif
 
230
  sa.sa_handler = sig_child;
 
231
  sigemptyset (&sa.sa_mask);
 
232
  sigaction (SIGCHLD, &sa, NULL);
 
233
  /* If program quits, give ports free. */
 
234
  sigaction (SIGTERM, NULL, &sa);
 
235
#if !defined(sun) || (defined(sun) && defined(__svr4__))
 
236
  sa.sa_flags |= SA_RESTART;
 
237
#endif
 
238
  sa.sa_handler = sig_quit;
 
239
  sigemptyset (&sa.sa_mask);
 
240
  sigaction (SIGTERM, &sa, NULL);
 
241
 
 
242
  sigaction (SIGINT, NULL, &sa);
 
243
#if !defined(sun) || (defined(sun) && defined(__svr4__))
 
244
  sa.sa_flags |= SA_RESTART;
 
245
#endif
 
246
  sa.sa_handler = sig_quit;
 
247
  sigemptyset (&sa.sa_mask);
 
248
  sigaction (SIGINT, &sa, NULL);
 
249
}
 
250
 
 
251
 
 
252
int
 
253
main (int argc, char **argv)
 
254
{
 
255
  SVCXPRT *transp;
 
256
  int my_port = -1, my_socket;
 
257
  int c;
 
258
 
 
259
  /* Initialize logging. */
 
260
  openlog ("rpc.yppasswdd", LOG_PID, LOG_AUTH);
 
261
 
 
262
  /* Parse the command line options and arguments. */
 
263
  while (1)
 
264
    {
 
265
      int option_index = 0;
 
266
      static struct option long_options[] =
 
267
      {
 
268
        {"version", no_argument, NULL, '\255'},
 
269
        {"usage", no_argument, NULL, 'h'},
 
270
        {"help", no_argument, NULL, 'h'},
 
271
        {"execute", required_argument, NULL, 'x'},
 
272
        {"debug", no_argument, NULL, '\254'},
 
273
        {"port", required_argument, NULL, '\253'},
 
274
        {NULL, 0, NULL, '\0'}
 
275
      };
 
276
 
 
277
      c=getopt_long (argc, argv, "e:p:s:uhvD:E:x:m", long_options,
 
278
                     &option_index);
 
279
      if (c == EOF)
 
280
        break;
 
281
      switch (c)
 
282
        {
 
283
        case 'e':
 
284
          if (!strcmp (optarg, "chsh"))
 
285
            allow_chsh = 1;
 
286
          else if (!strcmp (optarg, "chfn"))
 
287
            allow_chfn = 1;
 
288
          else
 
289
            usage (stderr, 1);
 
290
          break;
 
291
        case 'p':
 
292
          if (solaris_mode == 1)
 
293
            usage (stderr, 1);
 
294
          solaris_mode = 0;
 
295
          path_passwd = optarg;
 
296
          break;
 
297
        case 's':
 
298
          if (solaris_mode == 1)
 
299
            usage (stderr, 1);
 
300
          solaris_mode = 0;
 
301
#ifdef HAVE_GETSPNAM
 
302
          path_shadow = optarg;
 
303
#endif
 
304
          break;
 
305
        case 'D':
 
306
          if (solaris_mode == 0)
 
307
            usage (stderr, 1);
 
308
          solaris_mode = 1;
 
309
          path_passwd = malloc (strlen (optarg) + 8);
 
310
          sprintf (path_passwd, "%s/passwd", optarg);
 
311
#ifdef HAVE_GETSPNAM
 
312
          path_shadow = malloc (strlen (optarg) + 8);
 
313
          sprintf (path_shadow, "%s/shadow", optarg);
 
314
#endif
 
315
          break;
 
316
        case 'E':
 
317
          external_update_program = strdup(optarg);
 
318
          x_flag = 0;
 
319
          break;
 
320
        case 'x':
 
321
          external_update_program = strdup(optarg);
 
322
          x_flag = 1;
 
323
          break;
 
324
        case 'm':
 
325
          if (solaris_mode == 0)
 
326
            usage (stderr, 1);
 
327
          solaris_mode = 1;
 
328
          /* do nothing for now. We always run make, and we uses the
 
329
             fastest arguments */
 
330
          break;
 
331
        case 'h':
 
332
          usage (stdout, 0);
 
333
          break;
 
334
        case '\253':
 
335
          my_port = atoi (optarg);
 
336
          if (debug_flag)
 
337
            log_msg ("Using port %d\n", my_port);
 
338
          break;
 
339
        case '\255':
 
340
#if CHECKROOT
 
341
          fprintf (stdout, "rpc.yppasswdd - YP server version %s (with CHECKROOT)\n",
 
342
                   VERSION);
 
343
#else /* NO CHECKROOT */
 
344
          fprintf (stdout, "rpc.yppasswdd - YP server version %s\n",
 
345
                   VERSION);
 
346
#endif /* CHECKROOT */
 
347
          exit (0);
 
348
        case '\254': /* --debug */
 
349
          debug_flag = 1;
 
350
          break;
 
351
        default:
 
352
          usage (stderr, 1);
 
353
        }
 
354
    }
 
355
 
 
356
  /* No more arguments allowed. */
 
357
  if (optind != argc)
 
358
    usage (stderr, 1);
 
359
 
 
360
  /* Create tmp and .OLD file names for "passwd" */
 
361
  path_passwd_tmp = malloc (strlen (path_passwd) + 5);
 
362
  if (path_passwd_tmp == NULL)
 
363
    {
 
364
      log_msg ("rpc.yppasswdd: out of memory\n");
 
365
      exit (-1);
 
366
    }
 
367
  sprintf (path_passwd_tmp, "%s.tmp", path_passwd);
 
368
  path_passwd_old = malloc (strlen (path_passwd) + 5);
 
369
  if (path_passwd_old == NULL)
 
370
    {
 
371
      log_msg ("rpc.yppasswdd: out of memory\n");
 
372
      exit (-1);
 
373
    }
 
374
  sprintf (path_passwd_old, "%s.OLD", path_passwd);
 
375
#ifdef HAVE_GETSPNAM
 
376
  /* Create tmp and .OLD file names for "shadow" */
 
377
  path_shadow_tmp = malloc (strlen (path_shadow) + 5);
 
378
  if (path_shadow_tmp == NULL)
 
379
    {
 
380
      log_msg ("rpc.yppasswdd: out of memory\n");
 
381
      exit (-1);
 
382
    }
 
383
  sprintf (path_shadow_tmp, "%s.tmp", path_shadow);
 
384
  path_shadow_old = malloc (strlen (path_shadow) + 5);
 
385
  if (path_shadow_old == NULL)
 
386
    {
 
387
      log_msg ("rpc.yppasswdd: out of memory\n");
 
388
      exit (-1);
 
389
    }
 
390
  sprintf (path_shadow_old, "%s.OLD", path_shadow);
 
391
#endif /* HAVE_GETSPNAM */
 
392
 
 
393
  if (debug_flag)
 
394
    {
 
395
#if CHECKROOT
 
396
      log_msg ("rpc.yppasswdd - NYS YP server version %s (with CHECKROOT)\n",
 
397
              VERSION);
 
398
#else /* NO CHECKROOT */
 
399
      log_msg ("rpc.yppasswdd - NYS YP server version %s\n", VERSION);
 
400
#endif /* CHECKROOT */
 
401
    }
 
402
  else
 
403
    {
 
404
      int i;
 
405
 
 
406
      /* We first fork off a child. */
 
407
      if ((i = fork ()) > 0)
 
408
        exit (0);
 
409
 
 
410
      if (i < 0)
 
411
        {
 
412
          log_msg ("rpc.yppasswdd: cannot fork: %s\n", strerror (errno));
 
413
          exit (-1);
 
414
        }
 
415
 
 
416
      if (setsid() == -1)
 
417
        {
 
418
          log_msg ("rpc.yppasswdd: cannot setsid: %s\n", strerror (errno));
 
419
          exit (-1);
 
420
        }
 
421
 
 
422
      if ((i = fork ()) > 0)
 
423
        exit (0);
 
424
 
 
425
      if (i < 0)
 
426
        {
 
427
          log_msg ("rpc.yppasswdd: cannot fork: %s\n", strerror (errno));
 
428
          exit (-1);
 
429
        }
 
430
 
 
431
      for (i = 0; i < getdtablesize (); ++i)
 
432
        close (i);
 
433
      errno = 0;
 
434
 
 
435
      chdir ("/");
 
436
      umask(0);
 
437
      i = open("/dev/null", O_RDWR);
 
438
      dup(i);
 
439
      dup(i);
 
440
    }
 
441
 
 
442
  create_pidfile ();
 
443
 
 
444
  /* Register a signal handler to reap children after they terminated */
 
445
  install_sighandler ();
 
446
 
 
447
  /* Create the RPC server */
 
448
  pmap_unset (YPPASSWDPROG, YPPASSWDVERS);
 
449
 
 
450
  if (my_port >= 0)
 
451
    {
 
452
      struct sockaddr_in s_in;
 
453
      int result;
 
454
 
 
455
      my_socket = socket (AF_INET, SOCK_DGRAM, 0);
 
456
      if (my_socket < 0)
 
457
        {
 
458
          log_msg ("can not create UDP: %s", strerror (errno));
 
459
          exit (1);
 
460
        }
 
461
 
 
462
      memset ((char *) &s_in, 0, sizeof (s_in));
 
463
      s_in.sin_family = AF_INET;
 
464
      s_in.sin_addr.s_addr = htonl (INADDR_ANY);
 
465
      s_in.sin_port = htons (my_port);
 
466
 
 
467
      result = bind (my_socket, (struct sockaddr *) &s_in,
 
468
                     sizeof (s_in));
 
469
      if (result < 0)
 
470
        {
 
471
          log_msg ("rpc.yppasswdd: can not bind UDP: %s ", strerror (errno));
 
472
          exit (1);
 
473
        }
 
474
    }
 
475
  else
 
476
    my_socket = RPC_ANYSOCK;
 
477
 
 
478
  transp = svcudp_create (my_socket);
 
479
  if (transp == NULL)
 
480
    {
 
481
      log_msg ("cannot create udp service.\n");
 
482
      exit (1);
 
483
    }
 
484
  if (!svc_register (transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1,
 
485
                     IPPROTO_UDP))
 
486
    {
 
487
      log_msg ("unable to register yppaswdd udp service.\n");
 
488
      exit (1);
 
489
    }
 
490
 
 
491
  /* Run the server */
 
492
  svc_run ();
 
493
  log_msg ("svc_run returned\n");
 
494
  unlink (_YPPASSWDD_PIDFILE);
 
495
  return 1;
 
496
}