LCOV - code coverage report
Current view: top level - openssh-6.6p1 - auth1.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 60 124 48.4 %
Date: 2014-08-01 Functions: 4 8 50.0 %
Branches: 35 82 42.7 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: auth1.c,v 1.80 2014/02/02 03:44:31 djm Exp $ */
       2                 :            : /*
       3                 :            :  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
       4                 :            :  *                    All rights reserved
       5                 :            :  *
       6                 :            :  * As far as I am concerned, the code I have written for this software
       7                 :            :  * can be used freely for any purpose.  Any derived versions of this
       8                 :            :  * software must be clearly marked as such, and if the derived work is
       9                 :            :  * incompatible with the protocol description in the RFC file, it must be
      10                 :            :  * called by a name other than "ssh" or "Secure Shell".
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "includes.h"
      14                 :            : 
      15                 :            : #include <sys/types.h>
      16                 :            : 
      17                 :            : #include <stdarg.h>
      18                 :            : #include <stdio.h>
      19                 :            : #include <string.h>
      20                 :            : #include <unistd.h>
      21                 :            : #include <pwd.h>
      22                 :            : 
      23                 :            : #include "openbsd-compat/sys-queue.h"
      24                 :            : #include "xmalloc.h"
      25                 :            : #include "rsa.h"
      26                 :            : #include "ssh1.h"
      27                 :            : #include "packet.h"
      28                 :            : #include "buffer.h"
      29                 :            : #include "log.h"
      30                 :            : #include "servconf.h"
      31                 :            : #include "compat.h"
      32                 :            : #include "key.h"
      33                 :            : #include "hostfile.h"
      34                 :            : #include "auth.h"
      35                 :            : #include "channels.h"
      36                 :            : #include "session.h"
      37                 :            : #include "uidswap.h"
      38                 :            : #ifdef GSSAPI
      39                 :            : #include "ssh-gss.h"
      40                 :            : #endif
      41                 :            : #include "monitor_wrap.h"
      42                 :            : #include "buffer.h"
      43                 :            : 
      44                 :            : /* import */
      45                 :            : extern ServerOptions options;
      46                 :            : extern Buffer loginmsg;
      47                 :            : 
      48                 :            : static int auth1_process_password(Authctxt *);
      49                 :            : static int auth1_process_rsa(Authctxt *);
      50                 :            : static int auth1_process_rhosts_rsa(Authctxt *);
      51                 :            : static int auth1_process_tis_challenge(Authctxt *);
      52                 :            : static int auth1_process_tis_response(Authctxt *);
      53                 :            : 
      54                 :            : static char *client_user = NULL;    /* Used to fill in remote user for PAM */
      55                 :            : 
      56                 :            : struct AuthMethod1 {
      57                 :            :         int type;
      58                 :            :         char *name;
      59                 :            :         int *enabled;
      60                 :            :         int (*method)(Authctxt *);
      61                 :            : };
      62                 :            : 
      63                 :            : const struct AuthMethod1 auth1_methods[] = {
      64                 :            :         {
      65                 :            :                 SSH_CMSG_AUTH_PASSWORD, "password",
      66                 :            :                 &options.password_authentication, auth1_process_password
      67                 :            :         },
      68                 :            :         {
      69                 :            :                 SSH_CMSG_AUTH_RSA, "rsa",
      70                 :            :                 &options.rsa_authentication, auth1_process_rsa
      71                 :            :         },
      72                 :            :         {
      73                 :            :                 SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
      74                 :            :                 &options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
      75                 :            :         },
      76                 :            :         {
      77                 :            :                 SSH_CMSG_AUTH_TIS, "challenge-response",
      78                 :            :                 &options.challenge_response_authentication,
      79                 :            :                 auth1_process_tis_challenge
      80                 :            :         },
      81                 :            :         {
      82                 :            :                 SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
      83                 :            :                 &options.challenge_response_authentication,
      84                 :            :                 auth1_process_tis_response
      85                 :            :         },
      86                 :            :         { -1, NULL, NULL, NULL}
      87                 :            : };
      88                 :            : 
      89                 :            : static const struct AuthMethod1
      90                 :            : *lookup_authmethod1(int type)
      91                 :            : {
      92                 :            :         int i;
      93                 :            : 
      94 [ +  - ][ +  - ]:        416 :         for (i = 0; auth1_methods[i].name != NULL; i++)
      95 [ +  + ][ +  + ]:        416 :                 if (auth1_methods[i].type == type)
      96                 :        208 :                         return (&(auth1_methods[i]));
      97                 :            : 
      98                 :            :         return (NULL);
      99                 :            : }
     100                 :            : 
     101                 :            : static char *
     102                 :        104 : get_authname(int type)
     103                 :            : {
     104                 :            :         const struct AuthMethod1 *a;
     105                 :            :         static char buf[64];
     106                 :            : 
     107         [ +  - ]:        104 :         if ((a = lookup_authmethod1(type)) != NULL)
     108                 :        104 :                 return (a->name);
     109                 :            :         snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
     110                 :          0 :         return (buf);
     111                 :            : }
     112                 :            : 
     113                 :            : /*ARGSUSED*/
     114                 :            : static int
     115                 :          0 : auth1_process_password(Authctxt *authctxt)
     116                 :            : {
     117                 :          0 :         int authenticated = 0;
     118                 :            :         char *password;
     119                 :            :         u_int dlen;
     120                 :            : 
     121                 :            :         /*
     122                 :            :          * Read user password.  It is in plain text, but was
     123                 :            :          * transmitted over the encrypted channel so it is
     124                 :            :          * not visible to an outside observer.
     125                 :            :          */
     126                 :          0 :         password = packet_get_string(&dlen);
     127         [ #  # ]:          0 :         packet_check_eom();
     128                 :            : 
     129                 :            :         /* Try authentication with the password. */
     130         [ #  # ]:          0 :         authenticated = PRIVSEP(auth_password(authctxt, password));
     131                 :            : 
     132                 :          0 :         explicit_bzero(password, dlen);
     133                 :          0 :         free(password);
     134                 :            : 
     135                 :          0 :         return (authenticated);
     136                 :            : }
     137                 :            : 
     138                 :            : /*ARGSUSED*/
     139                 :            : static int
     140                 :        104 : auth1_process_rsa(Authctxt *authctxt)
     141                 :            : {
     142                 :        104 :         int authenticated = 0;
     143                 :            :         BIGNUM *n;
     144                 :            : 
     145                 :            :         /* RSA authentication requested. */
     146         [ -  + ]:        104 :         if ((n = BN_new()) == NULL)
     147                 :          0 :                 fatal("do_authloop: BN_new failed");
     148                 :        104 :         packet_get_bignum(n);
     149         [ -  + ]:        104 :         packet_check_eom();
     150                 :        104 :         authenticated = auth_rsa(authctxt, n);
     151                 :        104 :         BN_clear_free(n);
     152                 :            : 
     153                 :        104 :         return (authenticated);
     154                 :            : }
     155                 :            : 
     156                 :            : /*ARGSUSED*/
     157                 :            : static int
     158                 :          0 : auth1_process_rhosts_rsa(Authctxt *authctxt)
     159                 :            : {
     160                 :          0 :         int keybits, authenticated = 0;
     161                 :            :         u_int bits;
     162                 :            :         Key *client_host_key;
     163                 :            :         u_int ulen;
     164                 :            : 
     165                 :            :         /*
     166                 :            :          * Get client user name.  Note that we just have to
     167                 :            :          * trust the client; root on the client machine can
     168                 :            :          * claim to be any user.
     169                 :            :          */
     170                 :          0 :         client_user = packet_get_cstring(&ulen);
     171                 :            : 
     172                 :            :         /* Get the client host key. */
     173                 :          0 :         client_host_key = key_new(KEY_RSA1);
     174                 :          0 :         bits = packet_get_int();
     175                 :          0 :         packet_get_bignum(client_host_key->rsa->e);
     176                 :          0 :         packet_get_bignum(client_host_key->rsa->n);
     177                 :            : 
     178                 :          0 :         keybits = BN_num_bits(client_host_key->rsa->n);
     179         [ #  # ]:          0 :         if (keybits < 0 || bits != (u_int)keybits) {
     180                 :          0 :                 verbose("Warning: keysize mismatch for client_host_key: "
     181                 :            :                     "actual %d, announced %d",
     182                 :          0 :                     BN_num_bits(client_host_key->rsa->n), bits);
     183                 :            :         }
     184         [ #  # ]:          0 :         packet_check_eom();
     185                 :            : 
     186                 :          0 :         authenticated = auth_rhosts_rsa(authctxt, client_user,
     187                 :            :             client_host_key);
     188                 :          0 :         key_free(client_host_key);
     189                 :            : 
     190                 :          0 :         auth_info(authctxt, "ruser %.100s", client_user);
     191                 :            : 
     192                 :          0 :         return (authenticated);
     193                 :            : }
     194                 :            : 
     195                 :            : /*ARGSUSED*/
     196                 :            : static int
     197                 :          0 : auth1_process_tis_challenge(Authctxt *authctxt)
     198                 :            : {
     199                 :            :         char *challenge;
     200                 :            : 
     201         [ #  # ]:          0 :         if ((challenge = get_challenge(authctxt)) == NULL)
     202                 :            :                 return (0);
     203                 :            : 
     204                 :          0 :         debug("sending challenge '%s'", challenge);
     205                 :          0 :         packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
     206                 :          0 :         packet_put_cstring(challenge);
     207                 :          0 :         free(challenge);
     208                 :          0 :         packet_send();
     209                 :          0 :         packet_write_wait();
     210                 :            : 
     211                 :          0 :         return (-1);
     212                 :            : }
     213                 :            : 
     214                 :            : /*ARGSUSED*/
     215                 :            : static int
     216                 :          0 : auth1_process_tis_response(Authctxt *authctxt)
     217                 :            : {
     218                 :          0 :         int authenticated = 0;
     219                 :            :         char *response;
     220                 :            :         u_int dlen;
     221                 :            : 
     222                 :          0 :         response = packet_get_string(&dlen);
     223         [ #  # ]:          0 :         packet_check_eom();
     224                 :          0 :         authenticated = verify_response(authctxt, response);
     225                 :          0 :         explicit_bzero(response, dlen);
     226                 :          0 :         free(response);
     227                 :            : 
     228                 :          0 :         return (authenticated);
     229                 :            : }
     230                 :            : 
     231                 :            : /*
     232                 :            :  * read packets, try to authenticate the user and
     233                 :            :  * return only if authentication is successful
     234                 :            :  */
     235                 :            : static void
     236                 :        104 : do_authloop(Authctxt *authctxt)
     237                 :            : {
     238                 :        104 :         int authenticated = 0;
     239                 :        104 :         int prev = 0, type = 0;
     240                 :            :         const struct AuthMethod1 *meth;
     241                 :            : 
     242         [ -  + ]:        104 :         debug("Attempting authentication for %s%.100s.",
     243                 :        104 :             authctxt->valid ? "" : "invalid user ", authctxt->user);
     244                 :            : 
     245                 :            :         /* If the user has no password, accept authentication immediately. */
     246 [ -  + ][ #  # ]:        104 :         if (options.permit_empty_passwd && options.password_authentication &&
         [ #  # ][ #  # ]
     247                 :            : #ifdef KRB5
     248                 :            :             (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
     249                 :            : #endif
     250                 :          0 :             PRIVSEP(auth_password(authctxt, ""))) {
     251                 :            : #ifdef USE_PAM
     252                 :            :                 if (options.use_pam && (PRIVSEP(do_pam_account())))
     253                 :            : #endif
     254                 :            :                 {
     255                 :          0 :                         auth_log(authctxt, 1, 0, "without authentication",
     256                 :            :                             NULL);
     257                 :          0 :                         return;
     258                 :            :                 }
     259                 :            :         }
     260                 :            : 
     261                 :            :         /* Indicate that authentication is needed. */
     262                 :        104 :         packet_start(SSH_SMSG_FAILURE);
     263                 :        104 :         packet_send();
     264                 :        104 :         packet_write_wait();
     265                 :            : 
     266                 :            :         for (;;) {
     267                 :            :                 /* default to fail */
     268                 :        104 :                 authenticated = 0;
     269                 :            : 
     270                 :            : 
     271                 :            :                 /* Get a packet from the client. */
     272                 :        104 :                 prev = type;
     273                 :        104 :                 type = packet_read();
     274                 :            : 
     275                 :            :                 /*
     276                 :            :                  * If we started challenge-response authentication but the
     277                 :            :                  * next packet is not a response to our challenge, release
     278                 :            :                  * the resources allocated by get_challenge() (which would
     279                 :            :                  * normally have been released by verify_response() had we
     280                 :            :                  * received such a response)
     281                 :            :                  */
     282         [ -  + ]:        104 :                 if (prev == SSH_CMSG_AUTH_TIS &&
     283                 :        104 :                     type != SSH_CMSG_AUTH_TIS_RESPONSE)
     284                 :          0 :                         abandon_challenge_response(authctxt);
     285                 :            : 
     286         [ +  - ]:        104 :                 if (authctxt->failures >= options.max_authtries)
     287                 :            :                         goto skip;
     288         [ -  + ]:        104 :                 if ((meth = lookup_authmethod1(type)) == NULL) {
     289                 :          0 :                         logit("Unknown message during authentication: "
     290                 :            :                             "type %d", type);
     291                 :          0 :                         goto skip;
     292                 :            :                 }
     293                 :            : 
     294         [ -  + ]:        104 :                 if (!*(meth->enabled)) {
     295                 :          0 :                         verbose("%s authentication disabled.", meth->name);
     296                 :          0 :                         goto skip;
     297                 :            :                 }
     298                 :            : 
     299                 :        104 :                 authenticated = meth->method(authctxt);
     300         [ -  + ]:        104 :                 if (authenticated == -1)
     301                 :          0 :                         continue; /* "postponed" */
     302                 :            : 
     303                 :            : #ifdef BSD_AUTH
     304                 :            :                 if (authctxt->as) {
     305                 :            :                         auth_close(authctxt->as);
     306                 :            :                         authctxt->as = NULL;
     307                 :            :                 }
     308                 :            : #endif
     309 [ -  + ][ #  # ]:        104 :                 if (!authctxt->valid && authenticated)
     310                 :          0 :                         fatal("INTERNAL ERROR: authenticated invalid user %s",
     311                 :            :                             authctxt->user);
     312                 :            : 
     313                 :            : #ifdef _UNICOS
     314                 :            :                 if (authenticated && cray_access_denied(authctxt->user)) {
     315                 :            :                         authenticated = 0;
     316                 :            :                         fatal("Access denied for user %s.",authctxt->user);
     317                 :            :                 }
     318                 :            : #endif /* _UNICOS */
     319                 :            : 
     320                 :            : #ifndef HAVE_CYGWIN
     321                 :            :                 /* Special handling for root */
     322         [ +  - ]:        104 :                 if (authenticated && authctxt->pw->pw_uid == 0 &&
           [ -  +  #  # ]
     323                 :          0 :                     !auth_root_allowed(meth->name)) {
     324                 :          0 :                         authenticated = 0;
     325                 :            : # ifdef SSH_AUDIT_EVENTS
     326                 :            :                         PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
     327                 :            : # endif
     328                 :            :                 }
     329                 :            : #endif
     330                 :            : 
     331                 :            : #ifdef USE_PAM
     332                 :            :                 if (options.use_pam && authenticated &&
     333                 :            :                     !PRIVSEP(do_pam_account())) {
     334                 :            :                         char *msg;
     335                 :            :                         size_t len;
     336                 :            : 
     337                 :            :                         error("Access denied for user %s by PAM account "
     338                 :            :                             "configuration", authctxt->user);
     339                 :            :                         len = buffer_len(&loginmsg);
     340                 :            :                         buffer_append(&loginmsg, "\0", 1);
     341                 :            :                         msg = buffer_ptr(&loginmsg);
     342                 :            :                         /* strip trailing newlines */
     343                 :            :                         if (len > 0)
     344                 :            :                                 while (len > 0 && msg[--len] == '\n')
     345                 :            :                                         msg[len] = '\0';
     346                 :            :                         else
     347                 :            :                                 msg = "Access denied.";
     348                 :            :                         packet_disconnect("%s", msg);
     349                 :            :                 }
     350                 :            : #endif
     351                 :            : 
     352                 :            :  skip:
     353                 :            :                 /* Log before sending the reply */
     354                 :        104 :                 auth_log(authctxt, authenticated, 0, get_authname(type), NULL);
     355                 :            : 
     356                 :        104 :                 free(client_user);
     357                 :        104 :                 client_user = NULL;
     358                 :            : 
     359         [ -  + ]:        104 :                 if (authenticated)
     360                 :            :                         return;
     361                 :            : 
     362         [ #  # ]:          0 :                 if (++authctxt->failures >= options.max_authtries) {
     363                 :            : #ifdef SSH_AUDIT_EVENTS
     364                 :            :                         PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
     365                 :            : #endif
     366                 :          0 :                         packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
     367                 :            :                 }
     368                 :            : 
     369                 :          0 :                 packet_start(SSH_SMSG_FAILURE);
     370                 :          0 :                 packet_send();
     371                 :          0 :                 packet_write_wait();
     372                 :            :         }
     373                 :            : }
     374                 :            : 
     375                 :            : /*
     376                 :            :  * Performs authentication of an incoming connection.  Session key has already
     377                 :            :  * been exchanged and encryption is enabled.
     378                 :            :  */
     379                 :            : void
     380                 :        104 : do_authentication(Authctxt *authctxt)
     381                 :            : {
     382                 :            :         u_int ulen;
     383                 :        104 :         char *user, *style = NULL;
     384                 :            : 
     385                 :            :         /* Get the name of the user that we wish to log in as. */
     386                 :        104 :         packet_read_expect(SSH_CMSG_USER);
     387                 :            : 
     388                 :            :         /* Get the user name. */
     389                 :        104 :         user = packet_get_cstring(&ulen);
     390         [ -  + ]:        104 :         packet_check_eom();
     391                 :            : 
     392         [ +  + ]:        104 :         if ((style = strchr(user, ':')) != NULL)
     393                 :          1 :                 *style++ = '\0';
     394                 :            : 
     395                 :        104 :         authctxt->user = user;
     396                 :        104 :         authctxt->style = style;
     397                 :            : 
     398                 :            :         /* Verify that the user is a valid user. */
     399 [ +  + ][ +  - ]:        104 :         if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
     400                 :        104 :                 authctxt->valid = 1;
     401                 :            :         else {
     402                 :          0 :                 debug("do_authentication: invalid user %s", user);
     403                 :          0 :                 authctxt->pw = fakepw();
     404                 :            :         }
     405                 :            : 
     406                 :            :         /* Configuration may have changed as a result of Match */
     407         [ -  + ]:        104 :         if (options.num_auth_methods != 0)
     408                 :          0 :                 fatal("AuthenticationMethods is not supported with SSH "
     409                 :            :                     "protocol 1");
     410                 :            : 
     411 [ +  + ][ +  - ]:        104 :         setproctitle("%s%s", authctxt->valid ? user : "unknown",
     412                 :        104 :             use_privsep ? " [net]" : "");
     413                 :            : 
     414                 :            : #ifdef USE_PAM
     415                 :            :         if (options.use_pam)
     416                 :            :                 PRIVSEP(start_pam(authctxt));
     417                 :            : #endif
     418                 :            : 
     419                 :            :         /*
     420                 :            :          * If we are not running as root, the user must have the same uid as
     421                 :            :          * the server.
     422                 :            :          */
     423                 :            : #ifndef HAVE_CYGWIN
     424 [ +  + ][ +  - ]:        105 :         if (!use_privsep && getuid() != 0 && authctxt->pw &&
           [ +  -  -  + ]
     425                 :          1 :             authctxt->pw->pw_uid != getuid())
     426                 :          0 :                 packet_disconnect("Cannot change user when server not running as root.");
     427                 :            : #endif
     428                 :            : 
     429                 :            :         /*
     430                 :            :          * Loop until the user has been authenticated or the connection is
     431                 :            :          * closed, do_authloop() returns only if authentication is successful
     432                 :            :          */
     433                 :        104 :         do_authloop(authctxt);
     434                 :            : 
     435                 :            :         /* The user has been authenticated and accepted. */
     436                 :        104 :         packet_start(SSH_SMSG_SUCCESS);
     437                 :        104 :         packet_send();
     438                 :        104 :         packet_write_wait();
     439                 :        104 : }

Generated by: LCOV version 1.9