示例#1
0
VGAuthError
ServiceStartUserConnection(const char *userName,
                           char **pipeName)
{
   ServiceConnection *userConn;
   VGAuthError err = VGAUTH_E_OK;
   gboolean connReuse = FALSE;
   gboolean bRet;

   /* Check if we can find the listening connection in the map */
   userConn = ServiceLookupListenConnection(userName);
   if (userConn) {
      connReuse = TRUE;
   }
#if LISTENCONN_NO_REUSE
   // remove from hash table which will call ServiceConnectionShutdown()
   (void) g_hash_table_remove(listenConnectionMap, userName);
#else
   bRet = UsercheckUserExists(userName);
   if (userConn) {
      if (bRet) {
         /*
          * If we have a cached conn -- and the user is still around (seems
          * like a weird corner case, but the 'deleted user' unit test hits
          * this) -- reuse.
          */
         *pipeName = g_strdup(userConn->pipeName);
         goto done;
       } else {
         /*
          * Have a conn, but can't find the user -- clean up before we make
          * a new conn.  This can happen if the service is hit by a network
          * glitch or the LDAP bug (see usercheck.c for details).
          *
          * Throw out the old, let it (try) to make a new.  If its the
          * LDAP bug, the listen will succeed, and we don't want to
          * end up with two userConn's for the same user.
          */
          Debug("%s: Already have a connection for user '%s', but the user "
                "check failed, so tearing down the connection and trying "
                "to rebuild\n",
                __FUNCTION__, userName);
         (void) g_hash_table_remove(listenConnectionMap, userName);
         // fall thru and let a new conn get created
      }
   }
#endif

   err = ServiceCreateUserConnection(userName, &userConn);
   if (err != VGAUTH_E_OK) {
      goto done;
   }

   err = (* startListeningIOFunc) (userConn);
   if (err != VGAUTH_E_OK) {
      goto done;
   }

   *pipeName = g_strdup(userConn->pipeName);

   /* Insert the new connection into the map */
   ServiceMapListenConnection(userName, userConn);

done:
   if (err != VGAUTH_E_OK && userConn) {
      if (connReuse) {
         VGAUTH_LOG_DEBUG("%s: removing dead userConn for %s from hashtable",
                          __FUNCTION__, userName);
         (void) g_hash_table_remove(listenConnectionMap, userName);
      } else {
         VGAUTH_LOG_DEBUG("%s: removing failed userConn for %s",
                          __FUNCTION__, userName);
         ServiceConnectionShutdown(userConn);
      }
   } else if (NULL != userConn) {
      g_get_current_time(&userConn->lastUse);
   }

   return err;
}
示例#2
0
VGAuthError
ServiceVerifyAndCheckTrustCertChainForSubject(int numCerts,
                                              const char **pemCertChain,
                                              const char *userName,
                                              ServiceSubject *subj,
                                              char **userNameOut,
                                              ServiceAliasInfo **verifyAi)
{
   VGAuthError err;
   int numMapped = 0;
   ServiceMappedAlias *maList = NULL;
   int numStoreCerts = 0;
   ServiceAlias *aList = NULL;
   int matchIdIdx = -1;
   int matchSiIdx = -1;
   ServiceAliasInfo *ai;
   char **trustedCerts = NULL;
   int numTrusted = 0;
   char **untrustedCerts = NULL;
   int numUntrusted = 0;
   char *queryUserName = NULL;
   char *leafCert = NULL;
   gboolean foundTrusted;
   int i;
   int j;
   int k;

   *userNameOut = NULL;
   *verifyAi = NULL;

   ASSERT(subj);
   ASSERT(numCerts > 0);

   /*
    * If we have no userName, look through the mapping file for a match
    * from the cert chain.
    */
   if (NULL == userName || *userName == '\0') {
      err = ServiceAliasQueryMappedAliases(&numMapped, &maList);

      if (VGAUTH_E_OK != err) {
         goto done;
      }
      if (0 == numMapped) {
         /*
          * No username, no mapped certs, no chance.
          */
         Debug("%s: no mapping entries or userName\n", __FUNCTION__);
         err = VGAUTH_E_AUTHENTICATION_DENIED;
         goto done;
      }

      /*
       * Search for a match in the mapped store.
       */
      for (i = 0; i < numCerts; i++) {
         for (j = 0; j < numMapped; j++) {
            if (ServiceComparePEMCerts(pemCertChain[i], maList[j].pemCert)) {
               /*
                * Make sure we don't have multiple matches with different users.
                * Two possible scenarios that can trigger this:
                * - the mapping file could be inconsistent
                * - the chain coming in could have more than one cert that
                *   exists in the mapping file, belonging to different users
                */
               if ((NULL != queryUserName) &&
                   g_strcmp0(queryUserName, maList[j].userName) != 0) {
                  Warning("%s: found more than one user in map file chain\n",
                          __FUNCTION__);
                  err = VGAUTH_E_MULTIPLE_MAPPINGS;
                  goto done;
               }

               for (k = 0; k < maList[j].num; k++) {
                  if ((maList[j].subjects[k].type == SUBJECT_TYPE_ANY) ||
                      ServiceAliasIsSubjectEqual(subj->type,
                                                 maList[j].subjects[k].type,
                                                 subj->name,
                                                 maList[j].subjects[k].name)) {
                     queryUserName = g_strdup(maList[j].userName);
                     break;
                  }
               }

            }
         }
      }
      /*
       * Subject went unmatched, so fail.
       */
      if (NULL == queryUserName) {
         Debug("%s: no matching subject found in mapping file\n",
               __FUNCTION__);
         err = VGAUTH_E_AUTHENTICATION_DENIED;
         goto done;
      }
   } else {
      queryUserName = g_strdup(userName);
   }

   /*
    * Make sure the user exists -- Query supports deleted users
    * to allow for cleanup.
    */
   if (!UsercheckUserExists(queryUserName)) {
      Debug("%s: User '%s' doesn't exist\n", __FUNCTION__, queryUserName);
      err = VGAUTH_E_AUTHENTICATION_DENIED;
      goto done;
   }

   err = ServiceAliasQueryAliases(queryUserName, &numStoreCerts, &aList);
   if (VGAUTH_E_OK != err) {
      goto done;
   }

   /*
    * Split the incoming chain into trusted and untrusted certs
    */
   for (i = 0; i < numCerts; i++) {
      int foundAnyIdx;
      int foundSubjectIdx;

      foundTrusted = FALSE;
      for (j = 0; j < numStoreCerts; j++) {
         if (ServiceComparePEMCerts(pemCertChain[i], aList[j].pemCert)) {
            /*
             * Remember the root cert, so we can return its AliasInfo
             * if all checks out.
             */
            matchIdIdx = j;
            foundAnyIdx = -1;
            foundSubjectIdx = -1;

            for (k = 0; k < aList[j].num; k++) {
               if (aList[j].infos[k].type == SUBJECT_TYPE_ANY) {
                  foundAnyIdx = k;
               } else if (ServiceAliasIsSubjectEqual(subj->type,
                                                     aList[j].infos[k].type,
                                                     subj->name,
                                                     aList[j].infos[k].name)) {
                  foundSubjectIdx = k;
               }
            }
            if ((foundSubjectIdx >= 0) || (foundAnyIdx >= 0)) {
               numTrusted++;
               trustedCerts = g_realloc(trustedCerts,
                                        numTrusted * sizeof(*trustedCerts));
               trustedCerts[numTrusted - 1] = g_strdup(pemCertChain[i]);
               foundTrusted = TRUE;
               /*
                * Remember the matching ai, so we can return its comment
                * if all checks out.  Note that a specific subject match takes
                * precendence over an ANY match.
                */
               matchSiIdx = (foundSubjectIdx >= 0) ?
                  foundSubjectIdx : foundAnyIdx;
            }
         }
      }
      if (!foundTrusted) {
         numUntrusted++;
         untrustedCerts = g_realloc(untrustedCerts,
                                    numUntrusted * sizeof(*untrustedCerts));
         untrustedCerts[numUntrusted - 1] = g_strdup(pemCertChain[i]);
      }
   }

   /*
    * Make sure we have at least one trusted cert.
    */
   if (numTrusted == 0) {
      err = VGAUTH_E_AUTHENTICATION_DENIED;
      Debug("%s: No trusted certs in chain\n", __FUNCTION__);
      goto done;
   }

   /*
    * Pull out the leaf -- it should be either the first trusted
    * or untrusted cert
    */
   if (g_strcmp0(pemCertChain[0], trustedCerts[0]) == 0) {
      numTrusted--;
      leafCert = trustedCerts[0];
      memmove(trustedCerts, &(trustedCerts[1]), sizeof(*trustedCerts) * numTrusted);
   } else if (g_strcmp0(pemCertChain[0], untrustedCerts[0]) == 0) {
      numUntrusted--;
      leafCert = untrustedCerts[0];
      memmove(untrustedCerts, &(untrustedCerts[1]), sizeof(*untrustedCerts) * numUntrusted);
   } else {
      ASSERT(0);
   }

   err = CertVerify_CertChain(leafCert,
                              numUntrusted,
                              (const char **) untrustedCerts,
                              numTrusted,
                              (const char **) trustedCerts);
   if (VGAUTH_E_OK != err) {
      goto done;
   }

   Debug("%s: cert chain successfully validated", __FUNCTION__);

   /*
    * Save off AliasInfo.
    *
    * XXX unclear on what should be done here if we have multiple
    * trusted certs in the alias store.  For now, use the root-most
    * (last found).
    */
   ai = g_malloc0(sizeof(ServiceAliasInfo));
   ASSERT(matchIdIdx >= 0 && matchSiIdx >= 0);
   ai->type = aList[matchIdIdx].infos[matchSiIdx].type;
   ai->name = g_strdup(aList[matchIdIdx].infos[matchSiIdx].name);
   ai->comment = g_strdup(aList[matchIdIdx].infos[matchSiIdx].comment);
   *verifyAi = ai;
   *userNameOut = queryUserName;
   queryUserName = NULL;

done:
   ServiceAliasFreeMappedAliasList(numMapped, maList);

   ServiceAliasFreeAliasList(numStoreCerts, aList);

   for (i = 0; i < numTrusted; i++) {
      g_free(trustedCerts[i]);
   }
   g_free(trustedCerts);

   for (i = 0; i < numUntrusted; i++) {
      g_free(untrustedCerts[i]);
   }
   g_free(untrustedCerts);

   g_free(leafCert);
   g_free(queryUserName);

   return err;
}