]> arthur.barton.de Git - netatalk.git/commitdiff
Merge remote branch 'sf/product-2-2' into develop
authorFrank Lahm <franklahm@googlemail.com>
Fri, 17 Aug 2012 12:21:52 +0000 (14:21 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Fri, 17 Aug 2012 12:21:52 +0000 (14:21 +0200)
Conflicts:
etc/afpd/afp_dsi.c
libatalk/dsi/dsi_stream.c

1  2 
NEWS
etc/afpd/afp_dsi.c
etc/afpd/auth.c
etc/uams/uams_dhx2_pam.c
include/atalk/globals.h

diff --combined NEWS
index cfb8f1730bd85626690d8ddb9fadbff7e810a588,9375ba0c8efe82e5c70c46f234a52625ca26fdb0..0e12964b643b480e0ae9725424333be19acd98da
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
 +Changes in 3.0.1
 +================
 +* NEW: afpd: Optional "ldap uuid encoding = string | ms-guid" parameter to
 +       afp.conf, allowing for usage of the binary objectGUID fields from
 +       Active Directory.
 +* FIX: afpd: Fix a Solaris 10 SPARC sendfilev bug
 +* FIX: afpd: Fix a crash on FreeBSD
 +* FIX: Fix possible alignment violations due to bad casts
 +* FIX: dbd: Fix logging
 +* FIX: apple_dump: Extended Attributes AppleDouble support for *BSD
 +* FIX: handling of '/' and ':' in volume name
 +* UPD: Install relevant includes necessary for building programs with
 +       installed headers and shared lib libatalk
 +* REM: Remove --with-smbsharemodes configure option, it was an
 +       empty stub not yet implemented
 +
 +Changes in 3.0
 +==============
 +
 +* UPD: afpd: force read only mode if cnid scheme is last
 +* REM: afpd: removed global option "icon"
 +* FIX: CNID path for user homes
 +
 +Changes in 3.0 beta2
 +====================
 +
 +* UPD: Solaris and friends: Replace initscript with SMF manifest
 +* FIX: Solaris and friends: resource fork handling
 +
 +Changes in 3.0 beta1
 +====================
 +
 +* UPD: afpd: Performance tuning of read/write AFP operations. New option
 +       "afp read locks" (default: no) which disables that the server
 +       applies UNIX byte range locks to regions of files in AFP read and
 +       write calls.
 +* UPD: apple_dump: Extended Attributes AppleDouble support.
 +       (*BSD is not supported yet)
 +
 +Changes in 3.0 alpha3
 +=====================
 +
 +* NEW: afpd: Per volume "login message", NetAFP bug ID #18
 +* NEW: afpd: Cross-platform locking (share modes) on Solaris and derivates
 +       with Solaris CIFS/SMB server. Uses new Solaris fcntl F_SHARE share
 +       reservation locking primitives. Enabled by default, set global
 +       "solaris share reservations" option to false to disable it.
 +* NEW: ad: ad set subcommand for changing Mac metadata on the server
 +* UPD: unix charset is UTF8 by default.
 +       vol charset is same value as unix charset by default.
 +* UPD: .AppleDesktop/ are stored in $localstatedir/netatalk/CNID
 +       (default: /var/netatalk/CNID), databases found in AFP volumes are
 +       automatically moved
 +* FIX: afpd: Server info packet was malformed resulting in broken
 +       server names being displayed on clients
 +* FIX: afpd: Byte order detection. Fixes an error where Netatalk on
 +       OpenIndiana returned wrong volume size information.
 +
 +Changes in 3.0 alpha2
 +=====================
 +
 +* UPD: afpd: Store '.' as is and '/' as ':' on the server, don't
 +       CAP hexencode as "2e" and "2f" respectively
 +* UPD: afdp: Automatic name conversion, renaming files and directories
 +       containing CAP sequences to their not enscaped forms
 +* UPD: afpd: Correct handling of user homes and users without homes
 +* UPD: afpd: Perform complete automatic adouble:v2 to adouble:ea conversion
 +       as root. Previously only unlinking the adouble:v2 file was done as root
 +* UPD: dbd: -C option removes CAP encoding
 +* UPD: Add graceful option to RedHat init script
 +* UPD: Add --disable-bundled-libevent configure options When set to yes,
 +       we rely on a properly installed version on libevent CPPFLAGS and LDFLAGS
 +       should be set properly to pick that up
 +* UPD: Run ldconfig on Linux at the end of make install
 +* FIX: afpd: ad cp on appledouble = ea volumes
 +* FIX: dbd: ignore ._ appledouble files
 +* REM: Volumes options "use dots" and "hex encoding"
 +
 +Changes in 3.0 alpha1
 +=====================
 +
 +* NEW: Central configuration file afp.conf which replaces all previous files
 +* NEW: netatalk: service controller starting and restarting afpd and cnid_metad
 +       as necessary
 +* NEW: afpd: Extended Attributes AppleDouble backend (default)
 +* UPD: CNID databases are stored in $localstatedir/netatalk/CNID
 +       (default: /var/netatalk/CNID), databases found in AFP volumes are
 +       automatically moved
 +* UPD: Start scripts and service manifests have been changed to only start
 +       the new netatalk service controller process
 +* UPD: afpd: UNIX privileges and use dots enabled by default
 +* UPD: afpd: Support for arbitrary AFP volumes using variable expansion has been
 +       removed
 +* UPD: afpd: afp_voluuid.conf and afp_signature.conf location has been
 +       changed to $localstatedir/netatalk/ (default: /var/netatalk/)
 +* UPD: afpd: default server messages dir changed to $localstatedir/netatalk/msg/
 +* UPD: dbd: new option -C for conversion from AppleDouble v2 to ea
 +* REM: AppleTalk support has been removed
 +* REM: afpd: SLP and AFP proxy support have been removed
 +* REM: afpd: legacy file extension to type/creator mapping has been removed
 +* REM: afpd: AppleDouble backends v1, osx and sfm have been removed
 +
  Changes in 2.2.4
  ================
  
  * FIX: Missing UAM links
  * FIX: Lockup in AFP logout on Fedora 17
+ * FIX: Reset signal handlers and alarm timer after successfull PAM
+        authentication. Fixes a problem with AFP disconnects caused
+        by pam_smbpass.so messing with our handlers and timer.
+ * FIX: afpd: Fix a possible problem with sendfile on Solaris derived
+        platforms
  
  Changes in 2.2.3
  ================
diff --combined etc/afpd/afp_dsi.c
index 8b1b1a8d7ce98624b41b0e0ae8edf22eaa195a06,8529177d6cf85588270148e1cca524cbcb64d54a..70caf468694d6318060fb69591acf8e940126b49
  #include <atalk/paths.h>
  #include <atalk/server_ipc.h>
  #include <atalk/fce_api.h>
 -
  #include <atalk/globals.h>
 +#include <atalk/netatalk_conf.h>
 +
  #include "switch.h"
  #include "auth.h"
  #include "fork.h"
  #include "dircache.h"
  
 -#ifdef FORCE_UIDGID
 -#warning UIDGID
 -#include "uid.h"
 -#endif /* FORCE_UIDGID */
 -
  #ifndef SOL_TCP
  #define SOL_TCP IPPROTO_TCP
  #endif
@@@ -75,7 -79,7 +75,7 @@@ static rc_elem_t replaycache[REPLAYCACH
  static sigjmp_buf recon_jmp;
  static void afp_dsi_close(AFPObj *obj)
  {
 -    DSI *dsi = obj->handle;
 +    DSI *dsi = obj->dsi;
      sigset_t sigs;
      
      close(obj->ipc_fd);
@@@ -93,7 -97,8 +93,7 @@@
          }
      }
  
 -    close_all_vol();
 -
 +    close_all_vol(obj);
      if (obj->logout) {
          /* Block sigs, PAM/systemd/whoever might send us a SIG??? in (*obj->logout)() -> pam_close_session() */
          sigfillset(&sigs);
   */
  static void afp_dsi_die(int sig)
  {
 -    DSI *dsi = (DSI *)AFPobj->handle;
 +    DSI *dsi = (DSI *)AFPobj->dsi;
  
      if (dsi->flags & DSI_RECONINPROG) {
          /* Primary reconnect succeeded, got SIGTERM from afpd parent */
          exit(0);
      }
  
 -    dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN);
 +    dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN);
      afp_dsi_close(AFPobj);
     if (sig) /* if no signal, assume dieing because logins are disabled &
                  don't log it (maintenance mode)*/
  /* SIGQUIT handler */
  static void ipc_reconnect_handler(int sig _U_)
  {
 -    DSI *dsi = (DSI *)AFPobj->handle;
 +    DSI *dsi = (DSI *)AFPobj->dsi;
  
      if (reconnect_ipc(AFPobj) != 0) {
          LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC reconnect");
@@@ -164,7 -169,7 +164,7 @@@ static void afp_dsi_transfer_session(in
  {
      uint16_t dsiID;
      int socket;
 -    DSI *dsi = (DSI *)AFPobj->handle;
 +    DSI *dsi = (DSI *)AFPobj->dsi;
  
      LOG(log_debug, logtype_afpd, "afp_dsi_transfer_session: got SIGURG, trying to receive session");
  
@@@ -215,13 -220,13 +215,13 @@@ static void afp_dsi_timedown(int sig _U
  {
      struct sigaction  sv;
      struct itimerval  it;
 -    DSI                 *dsi = (DSI *)AFPobj->handle;
 +    DSI                 *dsi = (DSI *)AFPobj->dsi;
      dsi->flags |= DSI_DIE;
      /* shutdown and don't reconnect. server going down in 5 minutes. */
      setmessage("The server is going down for maintenance.");
 -    if (dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
 +    if (dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
                    AFPATTN_MESG | AFPATTN_TIME(5)) < 0) {
 -        DSI *dsi = (DSI *)AFPobj->handle;
 +        DSI *dsi = (DSI *)AFPobj->dsi;
          dsi->down_request = 1;
      }                  
  
@@@ -278,17 -283,17 +278,17 @@@ static void afp_dsi_debug(int sig _U_
  /* ---------------------- */
  static void afp_dsi_getmesg (int sig _U_)
  {
 -    DSI *dsi = (DSI *)AFPobj->handle;
 +    DSI *dsi = (DSI *)AFPobj->dsi;
  
      dsi->msg_request = 1;
 -    if (dsi_attention(AFPobj->handle, AFPATTN_MESG | AFPATTN_TIME(5)) < 0)
 +    if (dsi_attention(AFPobj->dsi, AFPATTN_MESG | AFPATTN_TIME(5)) < 0)
          dsi->msg_request = 2;
  }
  
  static void alarm_handler(int sig _U_)
  {
      int err;
 -    DSI *dsi = (DSI *)AFPobj->handle;
 +    DSI *dsi = (DSI *)AFPobj->dsi;
  
      /* we have to restart the timer because some libraries may use alarm() */
      setitimer(ITIMER_REAL, &dsi->timer, NULL);
  
      if ((err = pollvoltime(AFPobj)) == 0)
          LOG(log_debug, logtype_afpd, "afp_alarm: sending DSI tickle");
 -        err = dsi_tickle(AFPobj->handle);
 +        err = dsi_tickle(AFPobj->dsi);
      if (err <= 0) {
          if (geteuid() == 0) {
              LOG(log_note, logtype_afpd, "afp_alarm: unauthenticated user, connection problem");
@@@ -366,35 -371,23 +366,26 @@@ static void pending_request(DSI *dsi
      if (dsi->msg_request) {
          if (dsi->msg_request == 2) {
              /* didn't send it in signal handler */
 -            dsi_attention(AFPobj->handle, AFPATTN_MESG | AFPATTN_TIME(5));
 +            dsi_attention(AFPobj->dsi, AFPATTN_MESG | AFPATTN_TIME(5));
          }
          dsi->msg_request = 0;
          readmessage(AFPobj);
      }
      if (dsi->down_request) {
          dsi->down_request = 0;
 -        dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
 +        dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
                    AFPATTN_MESG | AFPATTN_TIME(5));
      }
  }
  
- /* -------------------------------------------
-  afp over dsi. this never returns. 
- */
- void afp_over_dsi(AFPObj *obj)
+ void afp_over_dsi_sighandlers(AFPObj *obj)
  {
 -    DSI *dsi = (DSI *) obj->handle;
 +    DSI *dsi = (DSI *) obj->dsi;
 +    int rc_idx;
 +    uint32_t err, cmd;
 +    uint8_t function;
      struct sigaction action;
  
-     AFPobj = obj;
-     obj->exit = afp_dsi_die;
-     obj->reply = (int (*)()) dsi_cmdreply;
-     obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
-     dsi->tickle = 0;
      memset(&action, 0, sizeof(action));
      sigfillset(&action.sa_mask);
      action.sa_flags = SA_RESTART;
          afp_dsi_die(EXITERR_SYS);
      }
  #endif /* DEBUGGING */
+ }
+ /* -------------------------------------------
+  afp over dsi. this never returns. 
+ */
+ void afp_over_dsi(AFPObj *obj)
+ {
+     DSI *dsi = (DSI *) obj->handle;
+     int rc_idx;
+     u_int32_t err, cmd;
+     u_int8_t function;
+     AFPobj = obj;
+     obj->exit = afp_dsi_die;
+     obj->reply = (int (*)()) dsi_cmdreply;
+     obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
+     dsi->tickle = 0;
+     afp_over_dsi_sighandlers(obj);
  
      if (dircache_init(obj->options.dircachesize) != 0)
          afp_dsi_die(EXITERR_SYS);
  
          if (reload_request) {
              reload_request = 0;
 -            load_volumes(AFPobj);
 +            load_volumes(AFPobj, closevol);
          }
  
          /* The first SIGINT enables debugging, the next restores the config */
  
              if (debugging) {
                  if (obj->options.logconfig)
 -                    setuplog(obj->options.logconfig);
 +                    setuplog(obj->options.logconfig, obj->options.logfile);
                  else
 -                    setuplog("default log_note");
 +                    setuplog("default:note", NULL);
                  debugging = 0;
              } else {
                  char logstr[50];
                  debugging = 1;
 -                sprintf(logstr, "default log_maxdebug /tmp/afpd.%u.XXXXXX", getpid());
 -                setuplog(logstr);
 +                sprintf(logstr, "/tmp/afpd.%u.XXXXXX", getpid());
 +                setuplog("default:maxdebug", logstr);
              }
          }
  
  
                      dir_free_invalid_q();
  
 -#ifdef FORCE_UIDGID
 -                    /* bring everything back to old euid, egid */
 -                    if (obj->force_uid)
 -                        restore_uidgid ( &obj->uidgid );
 -#endif /* FORCE_UIDGID */
                      dsi->flags &= ~DSI_RUNNING;
  
                      /* Add result to the AFP replay cache */
                      AfpNum2name(function), AfpErr2name(err));
  
                  dsi->flags &= ~DSI_RUNNING;
 -#ifdef FORCE_UIDGID
 -              /* bring everything back to old euid, egid */
 -              if (obj->force_uid)
 -                  restore_uidgid ( &obj->uidgid );
 -#endif /* FORCE_UIDGID */
              } else {
                  LOG(log_error, logtype_afpd, "(write) bad function %x", function);
                  dsi->datalen = 0;
diff --combined etc/afpd/auth.c
index 6c81b5e482301c9e4197642e6aec179bbde3e443,b3d0d9a2c0a35d301e91042b6cec62cbb17b6eac..7569cfefa7be0dabb190dc5ef7774749e9f8746b
  #include <stdio.h>
  #include <stdlib.h>
  #include <errno.h>
 -#ifdef HAVE_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #include <sys/types.h>
  #include <sys/param.h>
  #include <sys/stat.h>
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/afp.h>
  #include <atalk/compat.h>
  #include <atalk/util.h>
@@@ -50,7 -51,24 +50,7 @@@ extern void afp_get_cmdline( int *ac, c
  #include "acls.h"
  #endif
  
 -int afp_version = 11;
  static int afp_version_index;
 -
 -uid_t   uuid;
 -
 -#if defined( sun ) && !defined( __svr4__ ) || defined( ultrix )
 -
 -int *groups;
 -#define GROUPS_SIZE sizeof(int)
 -
 -#else /* sun __svr4__ ultrix */
 -
 -gid_t   *groups;
 -#define GROUPS_SIZE sizeof(gid_t)
 -#endif /* sun ultrix */
 -
 -int ngroups;
 -
  static struct uam_mod uam_modules = {NULL, NULL, &uam_modules, &uam_modules};
  static struct uam_obj uam_login = {"", "", 0, {{NULL, NULL, NULL, NULL }}, &uam_login,
                                     &uam_login};
@@@ -60,16 -78,23 +60,16 @@@ static struct uam_obj uam_changepw = {"
  static struct uam_obj *afp_uam = NULL;
  
  
 -void status_versions(char *data,
 -#ifndef NO_DDP
 -                     const ASP asp,
 -#endif
 -                     const DSI *dsi)
 +void status_versions( char *data, const DSI *dsi)
  {
      char                *start = data;
 -    u_int16_t           status;
 +    uint16_t           status;
      int         len, num, i, count = 0;
  
      memcpy(&status, start + AFPSTATUS_VERSOFF, sizeof(status));
      num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
  
      for ( i = 0; i < num; i++ ) {
 -#ifndef NO_DDP
 -        if ( !asp && (afp_versions[ i ].av_number <= 21)) continue;
 -#endif /* ! NO_DDP */
          if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue;
          count++;
      }
      *data++ = count;
  
      for ( i = 0; i < num; i++ ) {
 -#ifndef NO_DDP
 -        if ( !asp && (afp_versions[ i ].av_number <= 21)) continue;
 -#endif /* ! NO_DDP */
          if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue;
          len = strlen( afp_versions[ i ].av_name );
          *data++ = len;
  void status_uams(char *data, const char *authlist)
  {
      char                *start = data;
 -    u_int16_t           status;
 +    uint16_t           status;
      struct uam_obj      *uams;
      int         len, num = 0;
  
@@@ -125,7 -153,7 +125,7 @@@ static int send_reply(const AFPObj *obj
      if ((err == AFP_OK) || (err == AFPERR_AUTHCONT))
          return err;
  
 -    obj->reply(obj->handle, err);
 +    obj->reply(obj->dsi, err);
      obj->exit(0);
  
      return AFP_OK;
@@@ -145,7 -173,7 +145,7 @@@ static int afp_null_nolog(AFPObj *obj _
      return( AFPERR_NOOP );
  }
  
 -static int set_auth_switch(int expired)
 +static int set_auth_switch(const AFPObj *obj, int expired)
  {
      int i;
  
      }
      else {
          afp_switch = postauth_switch;
 -        switch (afp_version) {
 +        switch (obj->afp_version) {
  
          case 33:
          case 32:
@@@ -241,6 -269,45 +241,6 @@@ static int login(AFPObj *obj, struct pa
      LOG(log_note, logtype_afpd, "%s Login by %s",
          afp_versions[afp_version_index].av_name, pwd->pw_name);
  
 -#ifndef NO_DDP
 -    if (obj->proto == AFPPROTO_ASP) {
 -        ASP asp = obj->handle;
 -        int addr_net = ntohs( asp->asp_sat.sat_addr.s_net );
 -        int addr_node  = asp->asp_sat.sat_addr.s_node;
 -
 -        if (obj->options.authprintdir) {
 -            if(addr_net && addr_node) { /* Do we have a valid Appletalk address? */
 -                char nodename[256];
 -                FILE *fp;
 -                int mypid = getpid();
 -                struct stat stat_buf;
 -
 -                sprintf(nodename, "%s/net%d.%dnode%d", obj->options.authprintdir,
 -                        addr_net / 256, addr_net % 256, addr_node);
 -                LOG(log_info, logtype_afpd, "registering %s (uid %d) on %u.%u as %s",
 -                    pwd->pw_name, pwd->pw_uid, addr_net, addr_node, nodename);
 -
 -                if (stat(nodename, &stat_buf) == 0) { /* file exists */
 -                    if (S_ISREG(stat_buf.st_mode)) { /* normal file */
 -                        unlink(nodename);
 -                        fp = fopen(nodename, "w");
 -                        fprintf(fp, "%s:%d\n", pwd->pw_name, mypid);
 -                        fclose(fp);
 -                        chown( nodename, pwd->pw_uid, -1 );
 -                    } else { /* somebody is messing with us */
 -                        LOG(log_error, logtype_afpd, "print authfile %s is not a normal file, it will not be modified", nodename );
 -                    }
 -                } else { /* file 'nodename' does not exist */
 -                    fp = fopen(nodename, "w");
 -                    fprintf(fp, "%s:%d\n", pwd->pw_name, mypid);
 -                    fclose(fp);
 -                    chown( nodename, pwd->pw_uid, -1 );
 -                }
 -            } /* if (addr_net && addr_node ) */
 -        } /* if (options->authprintdir) */
 -    } /* if (obj->proto == AFPPROTO_ASP) */
 -#endif
 -
      if (initgroups( pwd->pw_name, pwd->pw_gid ) < 0) {
  #ifdef RUN_AS_USER
          LOG(log_info, logtype_afpd, "running with uid %d", geteuid());
  
      /* Basically if the user is in the admin group, we stay root */
  
 -    if (( ngroups = getgroups( 0, NULL )) < 0 ) {
 +    if ((obj->ngroups = getgroups( 0, NULL )) < 0 ) {
          LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) );
          return AFPERR_BADUAM;
      }
  
 -    if ( NULL == (groups = calloc(ngroups, GROUPS_SIZE)) ) {
 -        LOG(log_error, logtype_afpd, "login: %s calloc: %d", ngroups);
 +    if ( NULL == (obj->groups = calloc(obj->ngroups, sizeof(gid_t))) ) {
 +        LOG(log_error, logtype_afpd, "login: %s calloc: %d", obj->ngroups);
          return AFPERR_BADUAM;
      }
  
 -    if (( ngroups = getgroups( ngroups, groups )) < 0 ) {
 +    if (( obj->ngroups = getgroups(obj->ngroups, obj->groups )) < 0 ) {
          LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) );
          return AFPERR_BADUAM;
      }
  
      if (obj->options.admingid != 0) {
          int i;
 -        for (i = 0; i < ngroups; i++) {
 -            if (groups[i] == obj->options.admingid) admin = 1;
 +        for (i = 0; i < obj->ngroups; i++) {
 +            if (obj->groups[i] == obj->options.admingid) admin = 1;
          }
      }
      if (admin) {
      }
  #endif /* TRU64 */
  
 -    LOG(log_debug, logtype_afpd, "login: supplementary groups: %s", print_groups(ngroups, groups));
 +    LOG(log_debug, logtype_afpd, "login: supplementary groups: %s", print_groups(obj->ngroups, obj->groups));
  
      /* There's probably a better way to do this, but for now, we just play root */
  #ifdef ADMIN_GRP
      if (admin)
 -        uuid = 0;
 +        obj->uid = 0;
      else
  #endif /* ADMIN_GRP */
 -        uuid = pwd->pw_uid;
 +        obj->uid = geteuid();
  
 -    set_auth_switch(expired);
 +    set_auth_switch(obj, expired);
      /* save our euid, we need it for preexec_close */
      obj->uid = geteuid();
      obj->logout = logout;
  
 -#ifdef FORCE_UIDGID
 -    obj->force_uid = 1;
 -    save_uidgid ( &obj->uidgid );
 -#endif
 -
      /* pam_umask or similar might have changed our umask */
      (void)umask(obj->options.umask);
  
+     /* Some PAM module might have reset our signal handlers and timer, so we need to reestablish them */
+     afp_over_dsi_sighandlers(obj);
      return( AFP_OK );
  }
  
  int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
  {
      uint32_t data;
 -    DSI *dsi = (DSI *)AFPobj->handle;
 +    DSI *dsi = (DSI *)AFPobj->dsi;
  
      *rbuflen = 0;
      ibuf += 2;
@@@ -442,10 -517,10 +445,10 @@@ int afp_getsession
      char   *ibuf, size_t ibuflen, 
      char   *rbuf, size_t *rbuflen)
  {
 -    u_int16_t           type;
 -    u_int32_t           idlen = 0;
 -    u_int32_t       boottime;
 -    u_int32_t           tklen, tp;
 +    uint16_t           type;
 +    uint32_t           idlen = 0;
 +    uint32_t       boottime;
 +    uint32_t           tklen, tp;
      char                *token;
      char                *p;
  
  /* ---------------------- */
  int afp_disconnect(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
  {
 -    DSI                 *dsi = (DSI *)obj->handle;
 -    u_int16_t           type;
 -    u_int32_t           tklen;
 +    DSI                 *dsi = (DSI *)obj->dsi;
 +    uint16_t           type;
 +    uint32_t           tklen;
      pid_t               token;
      int                 i;
  
@@@ -633,7 -708,7 +636,7 @@@ static int get_version(AFPObj *obj, cha
      num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ]);
      for ( i = 0; i < num; i++ ) {
          if ( strncmp( ibuf, afp_versions[ i ].av_name , len ) == 0 ) {
 -            afp_version = afp_versions[ i ].av_number;
 +            obj->afp_version = afp_versions[ i ].av_number;
              afp_version_index = i;
              break;
          }
      if ( i == num )                 /* An inappropo version */
          return AFPERR_BADVERS ;
  
 -    if (afp_version >= 30 && obj->proto != AFPPROTO_DSI)
 -        return AFPERR_BADVERS ;
 -
      /* FIXME Hack */
 -    if (afp_version >= 30 && sizeof(off_t) != 8) {
 +    if (obj->afp_version >= 30 && sizeof(off_t) != 8) {
          LOG(log_error, logtype_afpd, "get_version: no LARGE_FILE support recompile!" );
          return AFPERR_BADVERS ;
      }
@@@ -708,7 -786,7 +711,7 @@@ int afp_login_ext(AFPObj *obj, char *ib
      size_t  len;
      int     i;
      char        type;
 -    u_int16_t   len16;
 +    uint16_t   len16;
      char        *username;
  
      *rbuflen = 0;
@@@ -851,11 -929,11 +854,11 @@@ int afp_logincont(AFPObj *obj, char *ib
  
  int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_, size_t *rbuflen)
  {
 -    DSI *dsi = (DSI *)(obj->handle);
 +    DSI *dsi = (DSI *)(obj->dsi);
  
      LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username);
 -    of_close_all_forks();
 -    close_all_vol();
 +    of_close_all_forks(obj);
 +    close_all_vol(obj);
      dsi->flags = DSI_AFP_LOGGED_OUT;
      *rbuflen = 0;
      return AFP_OK;
@@@ -894,7 -972,7 +897,7 @@@ int afp_changepw(AFPObj *obj, char *ibu
      if ((len + 1) & 1) /* pad byte */
          ibuf++;
  
 -    if ( afp_version < 30) {
 +    if (obj->afp_version < 30) {
          len = (unsigned char) *ibuf++;
          if ( len > sizeof(username) - 1) {
              return AFPERR_PARAM;
          (ret == AFPERR_AUTHCONT) ? "continued" :
          (ret ? "failed" : "succeeded"));
      if ( ret == AFP_OK )
 -        set_auth_switch(0);
 +        set_auth_switch(obj, 0);
  
      return ret;
  }
  /* FPGetUserInfo */
  int afp_getuserinfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
  {
 -    u_int8_t  thisuser;
 -    u_int32_t id;
 -    u_int16_t bitmap;
 +    uint8_t  thisuser;
 +    uint32_t id;
 +    uint16_t bitmap;
      char *bitmapp;
  
      LOG(log_debug, logtype_afpd, "begin afp_getuserinfo:");
@@@ -1057,7 -1135,7 +1060,7 @@@ int auth_load(const char *path, const c
          return -1;
  
      strlcpy(buf, list, sizeof(buf));
 -    if ((p = strtok(buf, ",")) == NULL)
 +    if ((p = strtok(buf, ", ")) == NULL)
          return -1;
  
      strcpy(name, path);
          } else {
              LOG(log_info, logtype_afpd, "uam: uam not found (status=%d)", stat(name, &st));
          }
 -        p = strtok(NULL, ",");
 +        p = strtok(NULL, ", ");
      }
  
      return 0;
diff --combined etc/uams/uams_dhx2_pam.c
index 32958f851335ec299050b960b5ada7148051088d,b303f8fa71a5a23b8b6136f8196273e6e6309f33..d033d96b12c76e322a8fd143b90e283ff8847738
@@@ -46,7 -46,7 +46,7 @@@ static gcry_mpi_t p, g, Ra
  static gcry_mpi_t serverNonce;
  static char *K_MD5hash = NULL;
  static int K_hash_len;
 -static u_int16_t ID;
 +static uint16_t ID;
  
  /* The initialization vectors for CAST128 are fixed by Apple. */
  static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' };
@@@ -242,7 -242,6 +242,7 @@@ static int dhx2_setup(void *obj, char *
      size_t nwritten;
      gcry_mpi_t Ma;
      char *Ra_binary = NULL;
 +    uint16_t uint16;
  
      *rbuflen = 0;
  
  
      /* Session ID first */
      ID = dhxhash(obj);
 -    *(u_int16_t *)rbuf = htons(ID);
 +    uint16 = htons(ID);
 +    memcpy(rbuf, &uint16, sizeof(uint16_t));
      rbuf += 2;
      *rbuflen += 2;
  
      *rbuflen += 4;
  
      /* len = length of p = PRIMEBITS/8 */
 -    *(u_int16_t *)rbuf = htons((u_int16_t) PRIMEBITS/8);
 +
 +    uint16 = htons((uint16_t) PRIMEBITS/8);
 +    memcpy(rbuf, &uint16, sizeof(uint16_t));
      rbuf += 2;
      *rbuflen += 2;
  
@@@ -369,7 -365,7 +369,7 @@@ static int pam_login_ext(void *obj, cha
  {
      char *username;
      size_t len, ulen;
 -    u_int16_t  temp16;
 +    uint16_t  temp16;
  
      *rbuflen = 0;
  
@@@ -407,7 -403,6 +407,7 @@@ static int logincont1(void *obj _U_, ch
      char serverNonce_bin[16];
      gcry_cipher_hd_t ctx;
      gcry_error_t ctxerror;
 +    uint16_t uint16;
  
      *rbuflen = 0;
  
      /* ---- Start building reply packet ---- */
  
      /* Session ID + 1 first */
 -    *(u_int16_t *)rbuf = htons(ID+1);
 +    uint16 = htons(ID+1);
 +    memcpy(rbuf, &uint16, sizeof(uint16_t));
      rbuf += 2;
      *rbuflen += 2;
  
@@@ -653,6 -647,7 +653,7 @@@ static int logincont2(void *obj_in, str
      /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
      pam_set_item(pamh, PAM_TTY, "afpd");
      pam_set_item(pamh, PAM_RHOST, hostname);
+     pam_set_item(pamh, PAM_RUSER, PAM_username);
  
      PAM_error = pam_authenticate(pamh, 0);
      if (PAM_error != PAM_SUCCESS) {
@@@ -720,12 -715,11 +721,12 @@@ static int pam_logincont(void *obj, str
                           char *ibuf, size_t ibuflen,
                           char *rbuf, size_t *rbuflen)
  {
 -    u_int16_t retID;
 +    uint16_t retID;
      int ret;
  
      /* check for session id */
 -    retID = ntohs(*(u_int16_t *)ibuf);
 +    memcpy(&retID, ibuf, sizeof(uint16_t));
 +    retID = ntohs(retID);
      if (retID == ID)
          ret = logincont1(obj, ibuf, ibuflen, rbuf, rbuflen);
      else if (retID == ID+1)
diff --combined include/atalk/globals.h
index 5d66c33c887bad2708d43cba902d2485a1bdd549,3c458d5d55d8f64b46981e05a445ac8be7d07d6b..b8412d15d7c7b300f8b90b3c94a58ddeb96e374b
@@@ -7,18 -7,22 +7,18 @@@
  #define AFPD_GLOBALS_H 1
  
  #include <sys/param.h>
 -#include <sys/cdefs.h>
 -
 -#ifdef ADMIN_GRP
  #include <grp.h>
  #include <sys/types.h>
 -#endif /* ADMIN_GRP */
  
  #ifdef HAVE_NETDB_H
  #include <netdb.h>  /* this isn't header-protected under ultrix */
  #endif /* HAVE_NETDB_H */
  
 -#include <netatalk/at.h>
  #include <atalk/afp.h>
  #include <atalk/compat.h>
  #include <atalk/unicode.h>
  #include <atalk/uam.h>
 +#include <atalk/iniparser.h>
  
  /* #define DOSFILELEN 12 */             /* Type1, DOS-compat*/
  #define MACFILELEN 31                   /* Type2, HFS-compat */
  
  #define MAXUSERLEN 256
  
 +#define DEFAULT_MAX_DIRCACHE_SIZE 8192
 +
  #define OPTION_DEBUG         (1 << 0)
 -#define OPTION_USERVOLFIRST  (1 << 1)
 -#define OPTION_NOUSERVOL     (1 << 2)
 -#define OPTION_PROXY         (1 << 3)
 -#define OPTION_CUSTOMICON    (1 << 4)
 -#define OPTION_NOSLP         (1 << 5)
 +#define OPTION_CLOSEVOL      (1 << 1)
 +#define OPTION_SERVERNOTIF   (1 << 2)
 +#define OPTION_NOSENDFILE    (1 << 3)
 +/* #define OPTION_CUSTOMICON    (1 << 4) */
 +#define OPTION_AFP_READ_LOCK (1 << 5) /* whether to do AFP spec conforming read locks (default: no) */
  #define OPTION_ANNOUNCESSH   (1 << 6)
  #define OPTION_UUID          (1 << 7)
  #define OPTION_ACL2MACCESS   (1 << 8)
  #define OPTION_NOZEROCONF    (1 << 9)
  #define OPTION_KEEPSESSIONS  (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
 +#define OPTION_SHARE_RESERV  (1 << 11) /* whether to use Solaris fcntl F_SHARE locks */
 +
 +#define PASSWD_NONE     0
 +#define PASSWD_SET     (1 << 0)
 +#define PASSWD_NOSAVE  (1 << 1)
 +#define PASSWD_ALL     (PASSWD_SET | PASSWD_NOSAVE)
 +
 +#define IS_AFP_SESSION(obj) ((obj)->dsi && (obj)->dsi->serversock == -1)
  
 -#ifdef FORCE_UIDGID
 -/* set up a structure for this */
 -typedef struct uidgidset_t {
 -    uid_t uid;
 -    gid_t gid;
 -} uidgidset;
 -#endif /* FORCE_UIDGID */
 +/**********************************************************************************************
 + * Ini config sections
 + **********************************************************************************************/
 +
 +#define INISEC_GLOBAL "Global"
 +#define INISEC_HOMES  "Homes"
 +
 +struct DSI;
 +#define AFPOBJ_TMPSIZ (MAXPATHLEN)
  
 -/* a couple of these options could get stuck in unions to save
 - * space. */
  struct afp_volume_name {
      time_t     mtime;
 -    char       *name;
 -    char       *full_name;
      int        loaded;
  };
  
  struct afp_options {
 -    int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
 +    int connections;            /* Maximum number of possible AFP connections */
 +    int tickleval;
 +    int timeout;
 +    int flags;
 +    int dircachesize;
      int sleep;                  /* Maximum time allowed to sleep (in tickles) */
      int disconnected;           /* Maximum time in disconnected state (in tickles) */
      int fce_fmodwait;           /* number of seconds FCE file mod events are put on hold */
      unsigned int tcp_sndbuf, tcp_rcvbuf;
 -    unsigned char passwdbits, passwdminlen, loginmaxfail;
 -    u_int32_t server_quantum;
 +    unsigned char passwdbits, passwdminlen;
 +    uint32_t server_quantum;
      int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */
 -    char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
 -#ifndef NO_DDP
 -    struct at_addr ddpaddr;
 -#endif
 +    char *hostname;
 +    char *listen, *port;
 +    char *Cnid_srv, *Cnid_port;
 +    char *configfile;
      char *uampath, *fqdn;
 -    char *pidfile;
      char *sigconffile;
      char *uuidconf;
 -    struct afp_volume_name defaultvol, systemvol, uservol;
 -    int  closevol;
 -
      char *guest, *loginmesg, *keyfile, *passwdfile;
      char *uamlist;
 -    char *authprintdir;
      char *signatureopt;
      unsigned char signature[16];
      char *k5service, *k5realm, *k5keytab;
 -    char *unixcodepage,*maccodepage;
 +    char *unixcodepage, *maccodepage, *volcodepage;
      charset_t maccharset, unixcharset; 
      mode_t umask;
      mode_t save_mask;
 -#ifdef ADMIN_GRP
      gid_t admingid;
 -#endif /* ADMIN_GRP */
      int    volnamelen;
 -
      /* default value for winbind authentication */
      char *ntdomain, *ntseparator;
      char *logconfig;
 -
 +    char *logfile;
      char *mimicmodel;
      char *adminauthuser;
 +    struct afp_volume_name volfile;
  };
  
 -#define AFPOBJ_TMPSIZ (MAXPATHLEN)
 -typedef struct _AFPObj {
 -    int proto;
 -    unsigned long servernum;
 -    void *handle;               /* either (DSI *) or (ASP *) */
 -    void *config; 
 +typedef struct AFPObj {
 +    const char *cmdlineconfigfile;
 +    int cmdlineflags;
 +    const void *signature;
 +    struct DSI *dsi;
      struct afp_options options;
 -    char *Obj, *Type, *Zone;
 +    dictionary *iniconfig;
      char username[MAXUSERLEN];
 -    void (*logout)(void), (*exit)(int);
 -    int (*reply)(void *, int);
 -    int (*attention)(void *, AFPUserBytes);
      /* to prevent confusion, only use these in afp_* calls */
      char oldtmp[AFPOBJ_TMPSIZ + 1], newtmp[AFPOBJ_TMPSIZ + 1];
      void *uam_cookie; /* cookie for uams */
      struct session_info  sinfo;
      uid_t uid;        /* client running user id */
      int ipc_fd; /* anonymous PF_UNIX socket for IPC with afpd parent */
 -#ifdef FORCE_UIDGID
 -    int                 force_uid;
 -    uidgidset         uidgid;
 -#endif
 +    gid_t *groups;
 +    int ngroups;
 +    int afp_version;
 +    /* Functions */
 +    void (*logout)(void);
 +    void (*exit)(int);
 +    int (*reply)(void *, int);
 +    int (*attention)(void *, AFPUserBytes);
  } AFPObj;
  
  /* typedef for AFP functions handlers */
@@@ -146,8 -145,10 +146,8 @@@ extern const char         *Cnid_port
  
  extern int  get_afp_errno   (const int param);
  extern void afp_options_init (struct afp_options *);
 -extern int afp_options_parse (int, char **, struct afp_options *);
 -extern int afp_options_parseline (char *, struct afp_options *);
 -extern void afp_options_free (struct afp_options *,
 -                                      const struct afp_options *);
 +extern void afp_options_parse_cmdline(AFPObj *obj, int ac, char **av);
 +extern void afp_options_free(struct afp_options *);
  extern void setmessage (const char *);
  extern void readmessage (AFPObj *);
  
@@@ -162,6 -163,9 +162,6 @@@ extern const char *AfpErr2name(int err)
  /* directory.c */
  extern struct dir rootParent;
  
 -#ifndef NO_DDP
 -extern void afp_over_asp (AFPObj *);
 -#endif /* NO_DDP */
  extern void afp_over_dsi (AFPObj *);
+ extern void afp_over_dsi_sighandlers(AFPObj *obj);
  #endif /* globals.h */