]> granicus.if.org Git - linux-pam/commitdiff
Add hostname resolution cache.
authorTomas Mraz <tmraz@fedoraproject.org>
Mon, 10 Oct 2011 12:02:10 +0000 (14:02 +0200)
committerTomas Mraz <tmraz@fedoraproject.org>
Mon, 10 Oct 2011 12:02:10 +0000 (14:02 +0200)
ChangeLog
modules/pam_access/pam_access.c

index 07f9f8b9b2a8181fadd385d5a9b1aa14315e70fb..80cda12c00960a4a8014268342f4eeb13c3db96d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2011-10-10  Tomas Mraz  <tm@t8m.info>
+
+       * modules/pam_access/pam_access.c: Add hostname resolution
+       cache.
+       (user_match): Clear the cache in fake_item.
+       (from_match): If from is not hostname, do not try to resolve it.
+       Cache the getaddrinfo() result.
+       (network_netmask_match): Cache the getaddrinfo() result.
+       (pam_sm_authenticate): Free the getaddrinfo() result.
+
 2011-09-30  Tomas Mraz  <tm@t8m.info>
 
        * doc/man/pam.conf-syntax.xml: Improve documentation of the
index 472116c34c1599334cbde459c94f5603a2fb8fe7..35b7d058d63b716b6c5b3785d12fdc6bb6429c49 100644 (file)
@@ -106,6 +106,8 @@ struct login_info {
     const char *fs;                    /* field separator */
     const char *sep;                   /* list-element separator */
     int from_remote_host;               /* If PAM_RHOST was used for from */
+    struct addrinfo *res;              /* Cached DNS resolution of from */
+    int gai_rv;                                /* Cached retval of getaddrinfo */
 };
 
 /* Parse module config arguments */
@@ -168,7 +170,7 @@ static int user_match (pam_handle_t *, char *, struct login_info *);
 static int group_match (pam_handle_t *, const char *, const char *, int);
 static int from_match (pam_handle_t *, char *, struct login_info *);
 static int string_match (pam_handle_t *, const char *, const char *, int);
-static int network_netmask_match (pam_handle_t *, const char *, const char *, int);
+static int network_netmask_match (pam_handle_t *, const char *, const char *, struct login_info *);
 
 
 /* isipaddr - find out if string provided is an IP address or not */
@@ -530,9 +532,16 @@ user_match (pam_handle_t *pamh, char *tok, struct login_info *item)
            return NO;
        memcpy (&fake_item, item, sizeof(fake_item));
        fake_item.from = item->hostname;
+       fake_item.gai_rv = 0;
+       fake_item.res = NULL;
+       fake_item.from_remote_host = 1; /* hostname should be resolvable */
        *at = 0;
-       return (user_match (pamh, tok, item) &&
-               from_match (pamh, at + 1, &fake_item));
+       if (!user_match (pamh, tok, item))
+               return NO;
+       rv = from_match (pamh, at + 1, &fake_item);
+       if (fake_item.gai_rv == 0 && fake_item.res)
+               freeaddrinfo(fake_item.res);
+       return rv;
     } else if (tok[0] == '@') {                        /* netgroup */
        const char *hostname = NULL;
        if (tok[1] == '@') {                    /* add hostname to netgroup match */
@@ -616,22 +625,24 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
        if ((str_len = strlen(string)) > (tok_len = strlen(tok))
            && strcasecmp(tok, string + str_len - tok_len) == 0)
            return (YES);
-    } else if (strcasecmp(tok, "LOCAL") == 0) {        /* local: no PAM_RHOSTS */
-       if (item->from_remote_host == 0)
+    } else if (item->from_remote_host == 0) {  /* local: no PAM_RHOSTS */
+       if (strcasecmp(tok, "LOCAL") == 0)
            return (YES);
     } else if (tok[(tok_len = strlen(tok)) - 1] == '.') {
-      struct addrinfo *res;
       struct addrinfo hint;
 
       memset (&hint, '\0', sizeof (hint));
       hint.ai_flags = AI_CANONNAME;
       hint.ai_family = AF_INET;
 
-      if (getaddrinfo (string, NULL, &hint, &res) != 0)
+      if (item->gai_rv != 0)
+       return NO;
+      else if (!item->res &&
+               (item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0)
        return NO;
       else
        {
-         struct addrinfo *runp = res;
+         struct addrinfo *runp = item->res;
 
           while (runp != NULL)
            {
@@ -647,17 +658,15 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
 
                  if (strncmp(tok, buf, tok_len) == 0)
                    {
-                     freeaddrinfo (res);
                      return YES;
                    }
                }
              runp = runp->ai_next;
            }
-         freeaddrinfo (res);
        }
     } else {
       /* Assume network/netmask with a IP of a host.  */
-      if (network_netmask_match(pamh, tok, string, item->debug))
+      if (network_netmask_match(pamh, tok, string, item))
        return YES;
     }
 
@@ -700,13 +709,13 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string,
  */
 static int
 network_netmask_match (pam_handle_t *pamh,
-                      const char *tok, const char *string, int debug)
+                      const char *tok, const char *string, struct login_info *item)
 {
     char *netmask_ptr;
     char netmask_string[MAXHOSTNAMELEN + 1];
     int addr_type;
 
-    if (debug)
+    if (item->debug)
     pam_syslog (pamh, LOG_DEBUG,
                "network_netmask_match: tok=%s, item=%s", tok, string);
     /* OK, check if tok is of type addr/mask */
@@ -751,18 +760,20 @@ network_netmask_match (pam_handle_t *pamh,
     if (isipaddr(string, NULL, NULL) != YES)
       {
        /* Assume network/netmask with a name of a host.  */
-       struct addrinfo *res;
        struct addrinfo hint;
 
        memset (&hint, '\0', sizeof (hint));
        hint.ai_flags = AI_CANONNAME;
        hint.ai_family = AF_UNSPEC;
 
-       if (getaddrinfo (string, NULL, &hint, &res) != 0)
+       if (item->gai_rv != 0)
+           return NO;
+       else if (!item->res &&
+               (item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0)
            return NO;
         else
          {
-           struct addrinfo *runp = res;
+           struct addrinfo *runp = item->res;
 
            while (runp != NULL)
              {
@@ -776,12 +787,10 @@ network_netmask_match (pam_handle_t *pamh,
 
                if (are_addresses_equal(buf, tok, netmask_ptr))
                  {
-                   freeaddrinfo (res);
                    return YES;
                  }
                runp = runp->ai_next;
              }
-           freeaddrinfo (res);
          }
       }
     else
@@ -803,6 +812,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
     const char *from;
     struct passwd *user_pw;
     char hostname[MAXHOSTNAMELEN + 1];
+    int rv;
 
 
     /* set username */
@@ -819,6 +829,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
     /*
      * Bundle up the arguments to avoid unnecessary clumsiness later on.
      */
+    memset(&loginfo, '\0', sizeof(loginfo));
     loginfo.user = user_pw;
     loginfo.config_file = PAM_ACCESS_CONFIG;
 
@@ -889,7 +900,12 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
        loginfo.hostname = NULL;
     }
 
-    if (login_access(pamh, &loginfo)) {
+    rv = login_access(pamh, &loginfo);
+
+    if (loginfo.gai_rv == 0 && loginfo.res)
+       freeaddrinfo(loginfo.res);
+
+    if (rv) {
        return (PAM_SUCCESS);
     } else {
        pam_syslog(pamh, LOG_ERR,