warn when starting without keys
[openafs.git] / src / update / server.c
index dca13f8..7a5e33b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -9,33 +9,20 @@
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
+#include <afs/procmgmt.h>
+#include <roken.h>
+#include <afs/opr.h>
 
-#include <afs/stds.h>
-#ifdef AFS_AIX32_ENV
-#include <signal.h>
-#endif
-#include <sys/types.h>
 #ifdef AFS_NT40_ENV
-#include <winsock2.h>
 #include <WINNT/afsevent.h>
-#include <fcntl.h>
-#include <io.h>
-#include <afs/dirent.h>
-#include <afs/procmgmt.h>
-#else
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/file.h>
-#include <dirent.h>
 #endif
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+
+#ifdef AFS_AIX_ENV
+#include <sys/statfs.h>
 #endif
-#include <sys/stat.h>
-#include <errno.h>
-#include <stdio.h>
+
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #include <rx/rxkad.h>
@@ -43,9 +30,7 @@
 #include <afs/afsutil.h>
 #include <afs/fileutil.h>
 #include <afs/com_err.h>
-#ifdef AFS_AIX_ENV
-#include <sys/statfs.h>
-#endif
+
 #include "update.h"
 #include "global.h"
 
@@ -77,29 +62,46 @@ update_rxstat_userok(struct rx_call *call)
 
 /*
  * PathInDirectory() -- determine if path is in directory (or is directory)
+ * Returns 1 if yes, 0 if no, -1 on error.
  */
 static int
 PathInDirectory(char *dir, char *path)
 {
-    int inDir = 0;
+    int inDir = 0, code;
     size_t dirLen;
-    char dirNorm[AFSDIR_PATH_MAX], pathNorm[AFSDIR_PATH_MAX];
+    char *dirNorm, *pathNorm;
 
 #ifdef AFS_NT40_ENV
     /* case-insensitive comparison of normalized, same-flavor (short) paths */
     DWORD status;
 
+    dirNorm = malloc(AFSDIR_PATH_MAX);
+    if (dirNorm == NULL)
+       return -1;
     status = GetShortPathName(dir, dirNorm, AFSDIR_PATH_MAX);
     if (status == 0 || status > AFSDIR_PATH_MAX) {
        /* can't convert path to short version; just use long version */
-       strcpy(dirNorm, dir);
+       free(dirNorm);
+       dirNorm = strdup(dir);
+       if (dirNorm == NULL)
+           return -1;
     }
     FilepathNormalize(dirNorm);
 
+    pathNorm = malloc(AFSDIR_PATH_MAX);
+    if (pathNorm == NULL) {
+       code = -1;
+       goto out;
+    }
     status = GetShortPathName(path, pathNorm, AFSDIR_PATH_MAX);
     if (status == 0 || status > AFSDIR_PATH_MAX) {
        /* can't convert path to short version; just use long version */
-       strcpy(pathNorm, path);
+       free(pathNorm);
+       pathNorm = strdup(path);
+       if (pathNorm == NULL) {
+           code = -1;
+           goto out;
+       }
     }
     FilepathNormalize(pathNorm);
 
@@ -113,10 +115,16 @@ PathInDirectory(char *dir, char *path)
     }
 #else
     /* case-sensitive comparison of normalized paths */
-    strcpy(dirNorm, dir);
+    dirNorm = strdup(dir);
+    if (dirNorm == NULL)
+       return -1;
     FilepathNormalize(dirNorm);
 
-    strcpy(pathNorm, path);
+    pathNorm = strdup(path);
+    if (pathNorm == NULL) {
+       code = -1;
+       goto out;
+    }
     FilepathNormalize(pathNorm);
 
     dirLen = strlen(dirNorm);
@@ -128,13 +136,17 @@ PathInDirectory(char *dir, char *path)
        }
     }
 #endif /* AFS_NT40_ENV */
-    return inDir;
+    code = 0;
+out:
+    free(dirNorm);
+    free(pathNorm);
+    return (code != 0) ? code : inDir;
 }
 
 int
 AuthOkay(struct rx_call *call, char *name)
 {
-    int i;
+    int i, r;
     rxkad_level level;
     afs_int32 code;
     int matches;
@@ -143,8 +155,8 @@ AuthOkay(struct rx_call *call, char *name)
     if (!afsconf_SuperUser(cdir, call, NULL))
        return 0;
 
-    if (rx_SecurityClassOf(rx_ConnectionOf(call)) == 2) {
-       code = rxkad_GetServerInfo(call->conn, &level, 0, 0, 0, 0, 0);
+    if (rx_SecurityClassOf(rx_ConnectionOf(call)) == RX_SECIDX_KAD) {
+       code = rxkad_GetServerInfo(rx_ConnectionOf(call), &level, 0, 0, 0, 0, 0);
        if (code)
            return 0;
     } else
@@ -152,7 +164,10 @@ AuthOkay(struct rx_call *call, char *name)
 
     matches = 0;
     for (i = 0; i < nDirs; i++) {
-       if (PathInDirectory(dirName[i], name)) {
+       r = PathInDirectory(dirName[i], name);
+       if (r < 0)
+           return 0;
+       if (r) {
            if (dirLevel[i] > level)
                return 0;
            matches++;
@@ -180,8 +195,10 @@ osi_audit(void)
 int
 main(int argc, char *argv[])
 {
-    struct rx_securityClass *securityObjects[3];
+    struct rx_securityClass **securityClasses;
+    afs_int32 numClasses;
     struct rx_service *service;
+    char hoststr[16];
     afs_uint32 host = htonl(INADDR_ANY);
 
     int a = 0;
@@ -190,8 +207,8 @@ main(int argc, char *argv[])
 
 #ifdef AFS_AIX32_ENV
     /*
-     * The following signal action for AIX is necessary so that in case of a 
-     * crash (i.e. core is generated) we can include the user's data section 
+     * The following signal action for AIX is necessary so that in case of a
+     * crash (i.e. core is generated) we can include the user's data section
      * in the core dump. Unfortunately, by default, only a partial core is
      * generated which, in many cases, isn't too useful.
      */
@@ -249,10 +266,8 @@ main(int argc, char *argv[])
          usage:
            Quit("Usage: upserver [<directory>+] [-crypt <directory>+] [-clear <directory>+] [-auth <directory>+] [-rxbind] [-help]\n");
        } else {
-           int dirlen;
            if (nDirs >= sizeof(dirName) / sizeof(dirName[0]))
                Quit("Too many dirs");
-           dirlen = strlen(argv[a]);
            if (AddObject(&dirName[nDirs], argv[a])) {
                printf("%s: Unable to export dir %s. Skipping\n", whoami,
                       argv[a]);
@@ -275,51 +290,47 @@ main(int argc, char *argv[])
        exit(1);
     }
 
+    if (afsconf_CountKeys(cdir) == 0) {
+       fprintf(stderr, "WARNING: No encryption keys found! "
+                       "All authenticated accesses will fail."
+                       "Run akeyconvert or asetkey to import encryption keys.\n");
+    }
+
     if (rxBind) {
        afs_int32 ccode;
-        if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || 
+        if (AFSDIR_SERVER_NETRESTRICT_FILEPATH ||
             AFSDIR_SERVER_NETINFO_FILEPATH) {
             char reason[1024];
-            ccode = parseNetFiles(SHostAddrs, NULL, NULL,
-                                           ADDRSPERSITE, reason,
-                                           AFSDIR_SERVER_NETINFO_FILEPATH,
-                                           AFSDIR_SERVER_NETRESTRICT_FILEPATH);
-        } else 
+            ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL,
+                                          ADDRSPERSITE, reason,
+                                          AFSDIR_SERVER_NETINFO_FILEPATH,
+                                          AFSDIR_SERVER_NETRESTRICT_FILEPATH);
+        } else
        {
             ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
         }
-        if (ccode == 1) 
+        if (ccode == 1)
             host = SHostAddrs[0];
     }
 
     /* Initialize Rx, telling it port number this server will use for its
      * single service */
+    fprintf(stderr, "upserver binding rx to %s:%d\n",
+            afs_inet_ntoa_r(host, hoststr), AFSCONF_UPDATEPORT);
     if (rx_InitHost(host, htons(AFSCONF_UPDATEPORT)) < 0)
        Quit("rx_init");
 
-    /* Create a single security object, in this case the null security object,
-     * for unauthenticated connections, which will be used to control security
-     * on connections made to this server. */
-
-    /* WHAT A JOKE!  Let's use rxkad at least so we know who we're talking to,
-     * then sometimes require full encryption. */
-
-    /* rxnull and rxvab are no longer supported */
-    securityObjects[0] = rxnull_NewServerSecurityObject();
-
-    securityObjects[1] = (struct rx_securityClass *)0;
+    afsconf_BuildServerSecurityObjects(cdir, &securityClasses, &numClasses);
 
-    securityObjects[2] =
-       rxkad_NewServerSecurityObject(rxkad_clear, cdir, afsconf_GetKey, 0);
-    if (securityObjects[2] == (struct rx_securityClass *)0)
+    if (securityClasses[2] == NULL)
        Quit("rxkad_NewServerSecurityObject");
 
     /* Instantiate a single UPDATE service.  The rxgen-generated procedure
      * which is called to decode requests is passed in here
      * (UPDATE_ExecuteRequest). */
     service =
-       rx_NewServiceHost(host, 0, UPDATE_SERVICEID, "UPDATE", securityObjects,
-                         3, UPDATE_ExecuteRequest);
+       rx_NewServiceHost(host, 0, UPDATE_SERVICEID, "UPDATE", securityClasses,
+                         numClasses, UPDATE_ExecuteRequest);
     if (service == (struct rx_service *)0)
        Quit("rx_NewService");
     rx_SetMaxProcs(service, 2);
@@ -403,12 +414,12 @@ UPDATE_FetchInfo(struct rx_call *call, char *name)
 static int
 Quit(char *msg)
 {
-    fprintf(stderr, msg);
+    fprintf(stderr, "%s", msg);
     exit(1);
 }
 
 int
-update_SendFile(register int fd, register struct rx_call *call, register struct stat *status)
+update_SendFile(int fd, struct rx_call *call, struct stat *status)
 {
     char *buffer = (char *)0;
     int blockSize;
@@ -428,15 +439,15 @@ update_SendFile(register int fd, register struct rx_call *call, register struct
     blockSize = status->st_blksize;
 #endif
     length = status->st_size;
-    buffer = (char *)malloc(blockSize);
+    buffer = malloc(blockSize);
     if (!buffer) {
        printf("malloc failed\n");
        return UPDATE_ERROR;
     }
     tlen = htonl(length);
-    rx_Write(call, &tlen, sizeof(afs_int32));  /* send length on fetch */
+    rx_Write(call, (char *)&tlen, sizeof(afs_int32));  /* send length on fetch */
     while (!error && length) {
-       register int nbytes = (length > blockSize ? blockSize : length);
+       int nbytes = (length > blockSize ? blockSize : length);
        nbytes = read(fd, buffer, nbytes);
        if (nbytes <= 0) {
            fprintf(stderr, "File system read failed\n");
@@ -453,19 +464,19 @@ update_SendFile(register int fd, register struct rx_call *call, register struct
     return error;
 }
 
-/* Enumerate dir (name) and write dir entry info into temp file. 
+/* Enumerate dir (name) and write dir entry info into temp file.
  */
 int
 update_SendDirInfo(char *name,         /* Name of dir to enumerate */
-     register struct rx_call *call,    /* rx call */
-     register struct stat *status,     /* stat struct for dir */
+     struct rx_call *call,     /* rx call */
+     struct stat *status,      /* stat struct for dir */
      char *origDir)            /* orig name of dir before being localized */
 {
     DIR *dirp;
     struct dirent *dp;
     FILE *stream;
     struct stat tstatus;
-    char filename[MAXSIZE], dirInfoFile[MAXSIZE];
+    char filename[MAXFNSIZE], dirInfoFile[MAXFNSIZE];
     int fd, tfd, errcode, error, err;
 
     error = 0;
@@ -487,7 +498,7 @@ update_SendDirInfo(char *name,              /* Name of dir to enumerate */
                goto fail;
            }
            if ((tstatus.st_mode & S_IFMT) != S_IFDIR) {        /* not a directory */
-               char dirEntry[MAXSIZE];
+               char dirEntry[MAXFNSIZE];
 
                strcpy(dirEntry, origDir);
                strcat(dirEntry, "/");
@@ -537,9 +548,9 @@ update_SendDirInfo(char *name,              /* Name of dir to enumerate */
 /* AddObject() - Adds the object to the list of exported objects after
  *     converting to a local path.
  *
- * expPath : points to allocated storage in which the exportable path is 
+ * expPath : points to allocated storage in which the exportable path is
  *           passed back.
- * dir     : dir name passed in for export 
+ * dir     : dir name passed in for export
  *
  */
 static int