[BACK]Return to monitor.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/monitor.c between version 1.9 and 1.9.2.4

version 1.9, 2002/03/30 18:51:15 version 1.9.2.4, 2002/10/11 14:51:52
Line 83 
Line 83 
         u_int ivinlen;          u_int ivinlen;
         u_char *ivout;          u_char *ivout;
         u_int ivoutlen;          u_int ivoutlen;
           u_char *ssh1key;
           u_int ssh1keylen;
         int ssh1cipher;          int ssh1cipher;
         int ssh1protoflags;          int ssh1protoflags;
         u_char *input;          u_char *input;
Line 96 
Line 98 
 int mm_answer_moduli(int, Buffer *);  int mm_answer_moduli(int, Buffer *);
 int mm_answer_sign(int, Buffer *);  int mm_answer_sign(int, Buffer *);
 int mm_answer_pwnamallow(int, Buffer *);  int mm_answer_pwnamallow(int, Buffer *);
   int mm_answer_auth2_read_banner(int, Buffer *);
 int mm_answer_authserv(int, Buffer *);  int mm_answer_authserv(int, Buffer *);
 int mm_answer_authpassword(int, Buffer *);  int mm_answer_authpassword(int, Buffer *);
 int mm_answer_bsdauthquery(int, Buffer *);  int mm_answer_bsdauthquery(int, Buffer *);
Line 113 
Line 116 
 int mm_answer_sesskey(int, Buffer *);  int mm_answer_sesskey(int, Buffer *);
 int mm_answer_sessid(int, Buffer *);  int mm_answer_sessid(int, Buffer *);
   
   #ifdef KRB4
   int mm_answer_krb4(int, Buffer *);
   #endif
   #ifdef KRB5
   int mm_answer_krb5(int, Buffer *);
   #endif
   
 static Authctxt *authctxt;  static Authctxt *authctxt;
 static BIGNUM *ssh1_challenge = NULL;   /* used for ssh1 rsa auth */  static BIGNUM *ssh1_challenge = NULL;   /* used for ssh1 rsa auth */
   
Line 120 
Line 130 
 static u_char *key_blob = NULL;  static u_char *key_blob = NULL;
 static u_int key_bloblen = 0;  static u_int key_bloblen = 0;
 static int key_blobtype = MM_NOKEY;  static int key_blobtype = MM_NOKEY;
 static u_char *hostbased_cuser = NULL;  static char *hostbased_cuser = NULL;
 static u_char *hostbased_chost = NULL;  static char *hostbased_chost = NULL;
 static char *auth_method = "unknown";  static char *auth_method = "unknown";
   static int session_id2_len = 0;
   static u_char *session_id2 = NULL;
   
 struct mon_table {  struct mon_table {
         enum monitor_reqtype type;          enum monitor_reqtype type;
Line 143 
Line 155 
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},      {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},      {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},      {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
       {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},      {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
 #ifdef BSD_AUTH  #ifdef BSD_AUTH
     {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},      {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
Line 183 
Line 196 
     {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},      {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
     {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},      {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
 #endif  #endif
   #ifdef KRB4
       {MONITOR_REQ_KRB4, MON_ONCE|MON_AUTH, mm_answer_krb4},
   #endif
   #ifdef KRB5
       {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5},
   #endif
     {0, 0, NULL}      {0, 0, NULL}
 };  };
   
Line 225 
Line 244 
 }  }
   
 Authctxt *  Authctxt *
 monitor_child_preauth(struct monitor *monitor)  monitor_child_preauth(struct monitor *pmonitor)
 {  {
         struct mon_table *ent;          struct mon_table *ent;
         int authenticated = 0;          int authenticated = 0;
Line 248 
Line 267 
   
         /* The first few requests do not require asynchronous access */          /* The first few requests do not require asynchronous access */
         while (!authenticated) {          while (!authenticated) {
                 authenticated = monitor_read(monitor, mon_dispatch, &ent);                  authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
                 if (authenticated) {                  if (authenticated) {
                         if (!(ent->flags & MON_AUTHDECIDE))                          if (!(ent->flags & MON_AUTHDECIDE))
                                 fatal("%s: unexpected authentication from %d",                                  fatal("%s: unexpected authentication from %d",
                                     __FUNCTION__, ent->type);                                      __func__, ent->type);
                         if (authctxt->pw->pw_uid == 0 &&                          if (authctxt->pw->pw_uid == 0 &&
                             !auth_root_allowed(auth_method))                              !auth_root_allowed(auth_method))
                                 authenticated = 0;                                  authenticated = 0;
Line 267 
Line 286 
         }          }
   
         if (!authctxt->valid)          if (!authctxt->valid)
                 fatal("%s: authenticated invalid user", __FUNCTION__);                  fatal("%s: authenticated invalid user", __func__);
   
         debug("%s: %s has been authenticated by privileged process",          debug("%s: %s has been authenticated by privileged process",
             __FUNCTION__, authctxt->user);              __func__, authctxt->user);
   
         mm_get_keystate(monitor);          mm_get_keystate(pmonitor);
   
         return (authctxt);          return (authctxt);
 }  }
   
 void  void
 monitor_child_postauth(struct monitor *monitor)  monitor_child_postauth(struct monitor *pmonitor)
 {  {
         if (compat20) {          if (compat20) {
                 mon_dispatch = mon_dispatch_postauth20;                  mon_dispatch = mon_dispatch_postauth20;
Line 298 
Line 317 
         }          }
   
         for (;;)          for (;;)
                 monitor_read(monitor, mon_dispatch, NULL);                  monitor_read(pmonitor, mon_dispatch, NULL);
 }  }
   
 void  void
 monitor_sync(struct monitor *monitor)  monitor_sync(struct monitor *pmonitor)
 {  {
         /* The member allocation is not visible, so sync it */          if (options.compression) {
         mm_share_sync(&monitor->m_zlib, &monitor->m_zback);                  /* The member allocation is not visible, so sync it */
                   mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback);
           }
 }  }
   
 int  int
 monitor_read(struct monitor *monitor, struct mon_table *ent,  monitor_read(struct monitor *pmonitor, struct mon_table *ent,
     struct mon_table **pent)      struct mon_table **pent)
 {  {
         Buffer m;          Buffer m;
Line 318 
Line 339 
   
         buffer_init(&m);          buffer_init(&m);
   
         mm_request_receive(monitor->m_sendfd, &m);          mm_request_receive(pmonitor->m_sendfd, &m);
         type = buffer_get_char(&m);          type = buffer_get_char(&m);
   
         debug3("%s: checking request %d", __FUNCTION__, type);          debug3("%s: checking request %d", __func__, type);
   
         while (ent->f != NULL) {          while (ent->f != NULL) {
                 if (ent->type == type)                  if (ent->type == type)
Line 331 
Line 352 
   
         if (ent->f != NULL) {          if (ent->f != NULL) {
                 if (!(ent->flags & MON_PERMIT))                  if (!(ent->flags & MON_PERMIT))
                         fatal("%s: unpermitted request %d", __FUNCTION__,                          fatal("%s: unpermitted request %d", __func__,
                             type);                              type);
                 ret = (*ent->f)(monitor->m_sendfd, &m);                  ret = (*ent->f)(pmonitor->m_sendfd, &m);
                 buffer_free(&m);                  buffer_free(&m);
   
                 /* The child may use this request only once, disable it */                  /* The child may use this request only once, disable it */
                 if (ent->flags & MON_ONCE) {                  if (ent->flags & MON_ONCE) {
                         debug2("%s: %d used once, disabling now", __FUNCTION__,                          debug2("%s: %d used once, disabling now", __func__,
                             type);                              type);
                         ent->flags &= ~MON_PERMIT;                          ent->flags &= ~MON_PERMIT;
                 }                  }
Line 349 
Line 370 
                 return ret;                  return ret;
         }          }
   
         fatal("%s: unsupported request: %d", __FUNCTION__, type);          fatal("%s: unsupported request: %d", __func__, type);
   
         /* NOTREACHED */          /* NOTREACHED */
         return (-1);          return (-1);
Line 394 
Line 415 
         max = buffer_get_int(m);          max = buffer_get_int(m);
   
         debug3("%s: got parameters: %d %d %d",          debug3("%s: got parameters: %d %d %d",
             __FUNCTION__, min, want, max);              __func__, min, want, max);
         /* We need to check here, too, in case the child got corrupted */          /* We need to check here, too, in case the child got corrupted */
         if (max < min || want < min || max < want)          if (max < min || want < min || max < want)
                 fatal("%s: bad parameters: %d %d %d",                  fatal("%s: bad parameters: %d %d %d",
                     __FUNCTION__, min, want, max);                      __func__, min, want, max);
   
         buffer_clear(m);          buffer_clear(m);
   
Line 427 
Line 448 
         u_int siglen, datlen;          u_int siglen, datlen;
         int keyid;          int keyid;
   
         debug3("%s", __FUNCTION__);          debug3("%s", __func__);
   
         keyid = buffer_get_int(m);          keyid = buffer_get_int(m);
         p = buffer_get_string(m, &datlen);          p = buffer_get_string(m, &datlen);
   
         if (datlen != 20)          if (datlen != 20)
                 fatal("%s: data length incorrect: %d", __FUNCTION__, datlen);                  fatal("%s: data length incorrect: %u", __func__, datlen);
   
           /* save session id, it will be passed on the first call */
           if (session_id2_len == 0) {
                   session_id2_len = datlen;
                   session_id2 = xmalloc(session_id2_len);
                   memcpy(session_id2, p, session_id2_len);
           }
   
         if ((key = get_hostkey_by_index(keyid)) == NULL)          if ((key = get_hostkey_by_index(keyid)) == NULL)
                 fatal("%s: no hostkey from index %d", __FUNCTION__, keyid);                  fatal("%s: no hostkey from index %d", __func__, keyid);
         if (key_sign(key, &signature, &siglen, p, datlen) < 0)          if (key_sign(key, &signature, &siglen, p, datlen) < 0)
                 fatal("%s: key_sign failed", __FUNCTION__);                  fatal("%s: key_sign failed", __func__);
   
         debug3("%s: signature %p(%d)", __FUNCTION__, signature, siglen);          debug3("%s: signature %p(%u)", __func__, signature, siglen);
   
         buffer_clear(m);          buffer_clear(m);
         buffer_put_string(m, signature, siglen);          buffer_put_string(m, signature, siglen);
Line 465 
Line 493 
         struct passwd *pwent;          struct passwd *pwent;
         int allowed = 0;          int allowed = 0;
   
         debug3("%s", __FUNCTION__);          debug3("%s", __func__);
   
         if (authctxt->attempt++ != 0)          if (authctxt->attempt++ != 0)
                 fatal("%s: multiple attempts for getpwnam", __FUNCTION__);                  fatal("%s: multiple attempts for getpwnam", __func__);
   
         login = buffer_get_string(m, NULL);          login = buffer_get_string(m, NULL);
   
Line 499 
Line 527 
         buffer_put_cstring(m, pwent->pw_shell);          buffer_put_cstring(m, pwent->pw_shell);
   
  out:   out:
         debug3("%s: sending MONITOR_ANS_PWNAM: %d", __FUNCTION__, allowed);          debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
         mm_request_send(socket, MONITOR_ANS_PWNAM, m);          mm_request_send(socket, MONITOR_ANS_PWNAM, m);
   
         /* For SSHv1 allow authentication now */          /* For SSHv1 allow authentication now */
         if (!compat20)          if (!compat20)
                 monitor_permit_authentications(1);                  monitor_permit_authentications(1);
         else          else {
                 /* Allow service/style information on the auth context */                  /* Allow service/style information on the auth context */
                 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);                  monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
                   monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
           }
   
   
         return (0);          return (0);
 }  }
   
   int mm_answer_auth2_read_banner(int socket, Buffer *m)
   {
           char *banner;
   
           buffer_clear(m);
           banner = auth2_read_banner();
           buffer_put_cstring(m, banner != NULL ? banner : "");
           mm_request_send(socket, MONITOR_ANS_AUTH2_READ_BANNER, m);
   
           if (banner != NULL)
                   xfree(banner);
   
           return (0);
   }
   
 int  int
 mm_answer_authserv(int socket, Buffer *m)  mm_answer_authserv(int socket, Buffer *m)
 {  {
Line 521 
Line 566 
         authctxt->service = buffer_get_string(m, NULL);          authctxt->service = buffer_get_string(m, NULL);
         authctxt->style = buffer_get_string(m, NULL);          authctxt->style = buffer_get_string(m, NULL);
         debug3("%s: service=%s, style=%s",          debug3("%s: service=%s, style=%s",
             __FUNCTION__, authctxt->service, authctxt->style);              __func__, authctxt->service, authctxt->style);
   
         if (strlen(authctxt->style) == 0) {          if (strlen(authctxt->style) == 0) {
                 xfree(authctxt->style);                  xfree(authctxt->style);
Line 536 
Line 581 
 {  {
         static int call_count;          static int call_count;
         char *passwd;          char *passwd;
         int authenticated, plen;          int authenticated;
           u_int plen;
   
         passwd = buffer_get_string(m, &plen);          passwd = buffer_get_string(m, &plen);
         /* Only authenticate if the context is valid */          /* Only authenticate if the context is valid */
         authenticated = authctxt->valid && auth_password(authctxt, passwd);          authenticated = options.password_authentication &&
               authctxt->valid && auth_password(authctxt, passwd);
         memset(passwd, 0, strlen(passwd));          memset(passwd, 0, strlen(passwd));
         xfree(passwd);          xfree(passwd);
   
         buffer_clear(m);          buffer_clear(m);
         buffer_put_int(m, authenticated);          buffer_put_int(m, authenticated);
   
         debug3("%s: sending result %d", __FUNCTION__, authenticated);          debug3("%s: sending result %d", __func__, authenticated);
         mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);          mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);
   
         call_count++;          call_count++;
Line 578 
Line 625 
         if (res != -1)          if (res != -1)
                 buffer_put_cstring(m, prompts[0]);                  buffer_put_cstring(m, prompts[0]);
   
         debug3("%s: sending challenge res: %d", __FUNCTION__, res);          debug3("%s: sending challenge res: %d", __func__, res);
         mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m);          mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m);
   
         if (res != -1) {          if (res != -1) {
Line 598 
Line 645 
         int authok;          int authok;
   
         if (authctxt->as == 0)          if (authctxt->as == 0)
                 fatal("%s: no bsd auth session", __FUNCTION__);                  fatal("%s: no bsd auth session", __func__);
   
         response = buffer_get_string(m, NULL);          response = buffer_get_string(m, NULL);
         authok = auth_userresponse(authctxt->as, response, 0);          authok = options.challenge_response_authentication &&
               auth_userresponse(authctxt->as, response, 0);
         authctxt->as = NULL;          authctxt->as = NULL;
         debug3("%s: <%s> = <%d>", __FUNCTION__, response, authok);          debug3("%s: <%s> = <%d>", __func__, response, authok);
         xfree(response);          xfree(response);
   
         buffer_clear(m);          buffer_clear(m);
         buffer_put_int(m, authok);          buffer_put_int(m, authok);
   
         debug3("%s: sending authenticated: %d", __FUNCTION__, authok);          debug3("%s: sending authenticated: %d", __func__, authok);
         mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m);          mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m);
   
         auth_method = "bsdauth";          auth_method = "bsdauth";
Line 633 
Line 681 
         if (res != -1)          if (res != -1)
                 buffer_put_cstring(m, challenge);                  buffer_put_cstring(m, challenge);
   
         debug3("%s: sending challenge res: %d", __FUNCTION__, res);          debug3("%s: sending challenge res: %d", __func__, res);
         mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m);          mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m);
   
         return (0);          return (0);
Line 647 
Line 695 
   
         response = buffer_get_string(m, NULL);          response = buffer_get_string(m, NULL);
   
         authok = (authctxt->valid &&          authok = (options.challenge_response_authentication &&
               authctxt->valid &&
             skey_haskey(authctxt->pw->pw_name) == 0 &&              skey_haskey(authctxt->pw->pw_name) == 0 &&
             skey_passcheck(authctxt->pw->pw_name, response) != -1);              skey_passcheck(authctxt->pw->pw_name, response) != -1);
   
Line 656 
Line 705 
         buffer_clear(m);          buffer_clear(m);
         buffer_put_int(m, authok);          buffer_put_int(m, authok);
   
         debug3("%s: sending authenticated: %d", __FUNCTION__, authok);          debug3("%s: sending authenticated: %d", __func__, authok);
         mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m);          mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m);
   
         auth_method = "skey";          auth_method = "skey";
Line 669 
Line 718 
 mm_append_debug(Buffer *m)  mm_append_debug(Buffer *m)
 {  {
         if (auth_debug_init && buffer_len(&auth_debug)) {          if (auth_debug_init && buffer_len(&auth_debug)) {
                 debug3("%s: Appending debug messages for child", __FUNCTION__);                  debug3("%s: Appending debug messages for child", __func__);
                 buffer_append(m, buffer_ptr(&auth_debug),                  buffer_append(m, buffer_ptr(&auth_debug),
                     buffer_len(&auth_debug));                      buffer_len(&auth_debug));
                 buffer_clear(&auth_debug);                  buffer_clear(&auth_debug);
Line 680 
Line 729 
 mm_answer_keyallowed(int socket, Buffer *m)  mm_answer_keyallowed(int socket, Buffer *m)
 {  {
         Key *key;          Key *key;
         u_char *cuser, *chost, *blob;          char *cuser, *chost;
           u_char *blob;
         u_int bloblen;          u_int bloblen;
         enum mm_keytype type = 0;          enum mm_keytype type = 0;
         int allowed = 0;          int allowed = 0;
   
         debug3("%s entering", __FUNCTION__);          debug3("%s entering", __func__);
   
         type = buffer_get_int(m);          type = buffer_get_int(m);
         cuser = buffer_get_string(m, NULL);          cuser = buffer_get_string(m, NULL);
Line 696 
Line 746 
   
         if ((compat20 && type == MM_RSAHOSTKEY) ||          if ((compat20 && type == MM_RSAHOSTKEY) ||
             (!compat20 && type != MM_RSAHOSTKEY))              (!compat20 && type != MM_RSAHOSTKEY))
                 fatal("%s: key type and protocol mismatch", __FUNCTION__);                  fatal("%s: key type and protocol mismatch", __func__);
   
         debug3("%s: key_from_blob: %p", __FUNCTION__, key);          debug3("%s: key_from_blob: %p", __func__, key);
   
         if (key != NULL && authctxt->pw != NULL) {          if (key != NULL && authctxt->pw != NULL) {
                 switch(type) {                  switch(type) {
                 case MM_USERKEY:                  case MM_USERKEY:
                         allowed = user_key_allowed(authctxt->pw, key);                          allowed = options.pubkey_authentication &&
                               user_key_allowed(authctxt->pw, key);
                         break;                          break;
                 case MM_HOSTKEY:                  case MM_HOSTKEY:
                         allowed = hostbased_key_allowed(authctxt->pw,                          allowed = options.hostbased_authentication &&
                               hostbased_key_allowed(authctxt->pw,
                             cuser, chost, key);                              cuser, chost, key);
                         break;                          break;
                 case MM_RSAHOSTKEY:                  case MM_RSAHOSTKEY:
                         key->type = KEY_RSA1; /* XXX */                          key->type = KEY_RSA1; /* XXX */
                         allowed = auth_rhosts_rsa_key_allowed(authctxt->pw,                          allowed = options.rhosts_rsa_authentication &&
                               auth_rhosts_rsa_key_allowed(authctxt->pw,
                             cuser, chost, key);                              cuser, chost, key);
                         break;                          break;
                 default:                  default:
                         fatal("%s: unknown key type %d", __FUNCTION__, type);                          fatal("%s: unknown key type %d", __func__, type);
                         break;                          break;
                 }                  }
                 key_free(key);                  key_free(key);
Line 734 
Line 787 
         }          }
   
         debug3("%s: key %p is %s",          debug3("%s: key %p is %s",
             __FUNCTION__, key, allowed ? "allowed" : "disallowed");              __func__, key, allowed ? "allowed" : "disallowed");
   
         buffer_clear(m);          buffer_clear(m);
         buffer_put_int(m, allowed);          buffer_put_int(m, allowed);
Line 753 
Line 806 
 monitor_valid_userblob(u_char *data, u_int datalen)  monitor_valid_userblob(u_char *data, u_int datalen)
 {  {
         Buffer b;          Buffer b;
         u_char *p;          char *p;
         u_int len;          u_int len;
         int fail = 0;          int fail = 0;
         int session_id2_len = 20 /*XXX should get from [net] */;  
   
         buffer_init(&b);          buffer_init(&b);
         buffer_append(&b, data, datalen);          buffer_append(&b, data, datalen);
   
         if (datafellows & SSH_OLD_SESSIONID) {          if (datafellows & SSH_OLD_SESSIONID) {
                   p = buffer_ptr(&b);
                   len = buffer_len(&b);
                   if ((session_id2 == NULL) ||
                       (len < session_id2_len) ||
                       (memcmp(p, session_id2, session_id2_len) != 0))
                           fail++;
                 buffer_consume(&b, session_id2_len);                  buffer_consume(&b, session_id2_len);
         } else {          } else {
                 xfree(buffer_get_string(&b, &len));                  p = buffer_get_string(&b, &len);
                 if (len != session_id2_len)                  if ((session_id2 == NULL) ||
                       (len != session_id2_len) ||
                       (memcmp(p, session_id2, session_id2_len) != 0))
                         fail++;                          fail++;
                   xfree(p);
         }          }
         if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)          if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
                 fail++;                  fail++;
Line 798 
Line 859 
 }  }
   
 static int  static int
 monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser,  monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
     u_char *chost)      char *chost)
 {  {
         Buffer b;          Buffer b;
         u_char *p;          char *p;
         u_int len;          u_int len;
         int fail = 0;          int fail = 0;
         int session_id2_len = 20 /*XXX should get from [net] */;  
   
         buffer_init(&b);          buffer_init(&b);
         buffer_append(&b, data, datalen);          buffer_append(&b, data, datalen);
   
         xfree(buffer_get_string(&b, &len));          p = buffer_get_string(&b, &len);
         if (len != session_id2_len)          if ((session_id2 == NULL) ||
               (len != session_id2_len) ||
               (memcmp(p, session_id2, session_id2_len) != 0))
                 fail++;                  fail++;
           xfree(p);
   
         if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)          if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
                 fail++;                  fail++;
         p = buffer_get_string(&b, NULL);          p = buffer_get_string(&b, NULL);
Line 865 
Line 929 
   
         if (hostbased_cuser == NULL || hostbased_chost == NULL ||          if (hostbased_cuser == NULL || hostbased_chost == NULL ||
           !monitor_allowed_key(blob, bloblen))            !monitor_allowed_key(blob, bloblen))
                 fatal("%s: bad key, not previously allowed", __FUNCTION__);                  fatal("%s: bad key, not previously allowed", __func__);
   
         key = key_from_blob(blob, bloblen);          key = key_from_blob(blob, bloblen);
         if (key == NULL)          if (key == NULL)
                 fatal("%s: bad public key blob", __FUNCTION__);                  fatal("%s: bad public key blob", __func__);
   
         switch (key_blobtype) {          switch (key_blobtype) {
         case MM_USERKEY:          case MM_USERKEY:
Line 884 
Line 948 
                 break;                  break;
         }          }
         if (!valid_data)          if (!valid_data)
                 fatal("%s: bad signature data blob", __FUNCTION__);                  fatal("%s: bad signature data blob", __func__);
   
         verified = key_verify(key, signature, signaturelen, data, datalen);          verified = key_verify(key, signature, signaturelen, data, datalen);
         debug3("%s: key %p signature %s",          debug3("%s: key %p signature %s",
             __FUNCTION__, key, verified ? "verified" : "unverified");              __func__, key, verified ? "verified" : "unverified");
   
         key_free(key);          key_free(key);
         xfree(blob);          xfree(blob);
         xfree(signature);          xfree(signature);
         xfree(data);          xfree(data);
   
           auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
   
         monitor_reset_key_state();          monitor_reset_key_state();
   
         buffer_clear(m);          buffer_clear(m);
         buffer_put_int(m, verified);          buffer_put_int(m, verified);
         mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);          mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);
   
         auth_method = "publickey";  
   
         return (verified);          return (verified);
 }  }
   
Line 917 
Line 981 
          * the address be 0.0.0.0.           * the address be 0.0.0.0.
          */           */
         memset(&from, 0, sizeof(from));          memset(&from, 0, sizeof(from));
           fromlen = sizeof(from);
         if (packet_connection_is_on_socket()) {          if (packet_connection_is_on_socket()) {
                 fromlen = sizeof(from);  
                 if (getpeername(packet_get_connection_in(),                  if (getpeername(packet_get_connection_in(),
                         (struct sockaddr *) & from, &fromlen) < 0) {                          (struct sockaddr *) & from, &fromlen) < 0) {
                         debug("getpeername: %.100s", strerror(errno));                          debug("getpeername: %.100s", strerror(errno));
Line 928 
Line 992 
         /* Record that there was a login on that tty from the remote host. */          /* Record that there was a login on that tty from the remote host. */
         record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,          record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
             get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),              get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
             (struct sockaddr *)&from);              (struct sockaddr *)&from, fromlen);
 }  }
   
 static void  static void
 mm_session_close(Session *s)  mm_session_close(Session *s)
 {  {
         debug3("%s: session %d pid %d", __FUNCTION__, s->self, s->pid);          debug3("%s: session %d pid %d", __func__, s->self, s->pid);
         if (s->ttyfd != -1) {          if (s->ttyfd != -1) {
                 debug3("%s: tty %s ptyfd %d",  __FUNCTION__, s->tty, s->ptyfd);                  debug3("%s: tty %s ptyfd %d",  __func__, s->tty, s->ptyfd);
                 fatal_remove_cleanup(session_pty_cleanup2, (void *)s);                  fatal_remove_cleanup(session_pty_cleanup2, (void *)s);
                 session_pty_cleanup2(s);                  session_pty_cleanup2(s);
         }          }
Line 946 
Line 1010 
 int  int
 mm_answer_pty(int socket, Buffer *m)  mm_answer_pty(int socket, Buffer *m)
 {  {
         extern struct monitor *monitor;          extern struct monitor *pmonitor;
         Session *s;          Session *s;
         int res, fd0;          int res, fd0;
   
         debug3("%s entering", __FUNCTION__);          debug3("%s entering", __func__);
   
         buffer_clear(m);          buffer_clear(m);
         s = session_new();          s = session_new();
Line 958 
Line 1022 
                 goto error;                  goto error;
         s->authctxt = authctxt;          s->authctxt = authctxt;
         s->pw = authctxt->pw;          s->pw = authctxt->pw;
         s->pid = monitor->m_pid;          s->pid = pmonitor->m_pid;
         res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));          res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
         if (res == 0)          if (res == 0)
                 goto error;                  goto error;
Line 974 
Line 1038 
   
         /* We need to trick ttyslot */          /* We need to trick ttyslot */
         if (dup2(s->ttyfd, 0) == -1)          if (dup2(s->ttyfd, 0) == -1)
                 fatal("%s: dup2", __FUNCTION__);                  fatal("%s: dup2", __func__);
   
         mm_record_login(s, authctxt->pw);          mm_record_login(s, authctxt->pw);
   
Line 983 
Line 1047 
   
         /* make sure nothing uses fd 0 */          /* make sure nothing uses fd 0 */
         if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)          if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
                 fatal("%s: open(/dev/null): %s", __FUNCTION__, strerror(errno));                  fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
         if (fd0 != 0)          if (fd0 != 0)
                 error("%s: fd0 %d != 0", __FUNCTION__, fd0);                  error("%s: fd0 %d != 0", __func__, fd0);
   
         /* slave is not needed */          /* slave is not needed */
         close(s->ttyfd);          close(s->ttyfd);
Line 993 
Line 1057 
         /* no need to dup() because nobody closes ptyfd */          /* no need to dup() because nobody closes ptyfd */
         s->ptymaster = s->ptyfd;          s->ptymaster = s->ptyfd;
   
         debug3("%s: tty %s ptyfd %d",  __FUNCTION__, s->tty, s->ttyfd);          debug3("%s: tty %s ptyfd %d",  __func__, s->tty, s->ttyfd);
   
         return (0);          return (0);
   
Line 1011 
Line 1075 
         Session *s;          Session *s;
         char *tty;          char *tty;
   
         debug3("%s entering", __FUNCTION__);          debug3("%s entering", __func__);
   
         tty = buffer_get_string(m, NULL);          tty = buffer_get_string(m, NULL);
         if ((s = session_by_tty(tty)) != NULL)          if ((s = session_by_tty(tty)) != NULL)
Line 1031 
Line 1095 
         monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);          monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
   
         if ((p = BN_new()) == NULL)          if ((p = BN_new()) == NULL)
                 fatal("%s: BN_new", __FUNCTION__);                  fatal("%s: BN_new", __func__);
   
         buffer_get_bignum2(m, p);          buffer_get_bignum2(m, p);
   
Line 1056 
Line 1120 
 {  {
         int i;          int i;
   
         debug3("%s entering", __FUNCTION__);          debug3("%s entering", __func__);
   
         if (buffer_len(m) != 16)          if (buffer_len(m) != 16)
                 fatal("%s: bad ssh1 session id", __FUNCTION__);                  fatal("%s: bad ssh1 session id", __func__);
         for (i = 0; i < 16; i++)          for (i = 0; i < 16; i++)
                 session_id[i] = buffer_get_char(m);                  session_id[i] = buffer_get_char(m);
   
Line 1078 
Line 1142 
         u_int blen = 0;          u_int blen = 0;
         int allowed = 0;          int allowed = 0;
   
         debug3("%s entering", __FUNCTION__);          debug3("%s entering", __func__);
   
         if (authctxt->valid) {          if (options.rsa_authentication && authctxt->valid) {
                 if ((client_n = BN_new()) == NULL)                  if ((client_n = BN_new()) == NULL)
                         fatal("%s: BN_new", __FUNCTION__);                          fatal("%s: BN_new", __func__);
                 buffer_get_bignum2(m, client_n);                  buffer_get_bignum2(m, client_n);
                 allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);                  allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
                 BN_clear_free(client_n);                  BN_clear_free(client_n);
Line 1096 
Line 1160 
         if (allowed && key != NULL) {          if (allowed && key != NULL) {
                 key->type = KEY_RSA;    /* cheat for key_to_blob */                  key->type = KEY_RSA;    /* cheat for key_to_blob */
                 if (key_to_blob(key, &blob, &blen) == 0)                  if (key_to_blob(key, &blob, &blen) == 0)
                         fatal("%s: key_to_blob failed", __FUNCTION__);                          fatal("%s: key_to_blob failed", __func__);
                 buffer_put_string(m, blob, blen);                  buffer_put_string(m, blob, blen);
   
                 /* Save temporarily for comparison in verify */                  /* Save temporarily for comparison in verify */
Line 1122 
Line 1186 
         u_char *blob;          u_char *blob;
         u_int blen;          u_int blen;
   
         debug3("%s entering", __FUNCTION__);          debug3("%s entering", __func__);
   
         if (!authctxt->valid)          if (!authctxt->valid)
                 fatal("%s: authctxt not valid", __FUNCTION__);                  fatal("%s: authctxt not valid", __func__);
         blob = buffer_get_string(m, &blen);          blob = buffer_get_string(m, &blen);
         if (!monitor_allowed_key(blob, blen))          if (!monitor_allowed_key(blob, blen))
                 fatal("%s: bad key, not previously allowed", __FUNCTION__);                  fatal("%s: bad key, not previously allowed", __func__);
         if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)          if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
                 fatal("%s: key type mismatch", __FUNCTION__);                  fatal("%s: key type mismatch", __func__);
         if ((key = key_from_blob(blob, blen)) == NULL)          if ((key = key_from_blob(blob, blen)) == NULL)
                 fatal("%s: received bad key", __FUNCTION__);                  fatal("%s: received bad key", __func__);
   
         if (ssh1_challenge)          if (ssh1_challenge)
                 BN_clear_free(ssh1_challenge);                  BN_clear_free(ssh1_challenge);
Line 1141 
Line 1205 
         buffer_clear(m);          buffer_clear(m);
         buffer_put_bignum2(m, ssh1_challenge);          buffer_put_bignum2(m, ssh1_challenge);
   
         debug3("%s sending reply", __FUNCTION__);          debug3("%s sending reply", __func__);
         mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m);          mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m);
   
         monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);          monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
Line 1156 
Line 1220 
         u_int blen, len;          u_int blen, len;
         int success;          int success;
   
         debug3("%s entering", __FUNCTION__);          debug3("%s entering", __func__);
   
         if (!authctxt->valid)          if (!authctxt->valid)
                 fatal("%s: authctxt not valid", __FUNCTION__);                  fatal("%s: authctxt not valid", __func__);
         if (ssh1_challenge == NULL)          if (ssh1_challenge == NULL)
                 fatal("%s: no ssh1_challenge", __FUNCTION__);                  fatal("%s: no ssh1_challenge", __func__);
   
         blob = buffer_get_string(m, &blen);          blob = buffer_get_string(m, &blen);
         if (!monitor_allowed_key(blob, blen))          if (!monitor_allowed_key(blob, blen))
                 fatal("%s: bad key, not previously allowed", __FUNCTION__);                  fatal("%s: bad key, not previously allowed", __func__);
         if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)          if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
                 fatal("%s: key type mismatch: %d", __FUNCTION__, key_blobtype);                  fatal("%s: key type mismatch: %d", __func__, key_blobtype);
         if ((key = key_from_blob(blob, blen)) == NULL)          if ((key = key_from_blob(blob, blen)) == NULL)
                 fatal("%s: received bad key", __FUNCTION__);                  fatal("%s: received bad key", __func__);
         response = buffer_get_string(m, &len);          response = buffer_get_string(m, &len);
         if (len != 16)          if (len != 16)
                 fatal("%s: received bad response to challenge", __FUNCTION__);                  fatal("%s: received bad response to challenge", __func__);
         success = auth_rsa_verify_response(key, ssh1_challenge, response);          success = auth_rsa_verify_response(key, ssh1_challenge, response);
   
         key_free(key);          key_free(key);
Line 1192 
Line 1256 
         return (success);          return (success);
 }  }
   
   #ifdef KRB4
 int  int
   mm_answer_krb4(int socket, Buffer *m)
   {
           KTEXT_ST auth, reply;
           char  *client, *p;
           int success;
           u_int alen;
   
           reply.length = auth.length = 0;
   
           p = buffer_get_string(m, &alen);
           if (alen >=  MAX_KTXT_LEN)
                    fatal("%s: auth too large", __func__);
           memcpy(auth.dat, p, alen);
           auth.length = alen;
           memset(p, 0, alen);
           xfree(p);
   
           success = options.kerberos_authentication &&
               authctxt->valid &&
               auth_krb4(authctxt, &auth, &client, &reply);
   
           memset(auth.dat, 0, alen);
           buffer_clear(m);
           buffer_put_int(m, success);
   
           if (success) {
                   buffer_put_cstring(m, client);
                   buffer_put_string(m, reply.dat, reply.length);
                   if (client)
                           xfree(client);
                   if (reply.length)
                           memset(reply.dat, 0, reply.length);
           }
   
           debug3("%s: sending result %d", __func__, success);
           mm_request_send(socket, MONITOR_ANS_KRB4, m);
   
           auth_method = "kerberos";
   
           /* Causes monitor loop to terminate if authenticated */
           return (success);
   }
   #endif
   
   #ifdef KRB5
   int
   mm_answer_krb5(int socket, Buffer *m)
   {
           krb5_data tkt, reply;
           char *client_user;
           u_int len;
           int success;
   
           /* use temporary var to avoid size issues on 64bit arch */
           tkt.data = buffer_get_string(m, &len);
           tkt.length = len;
   
           success = options.kerberos_authentication &&
               authctxt->valid &&
               auth_krb5(authctxt, &tkt, &client_user, &reply);
   
           if (tkt.length)
                   xfree(tkt.data);
   
           buffer_clear(m);
           buffer_put_int(m, success);
   
           if (success) {
                   buffer_put_cstring(m, client_user);
                   buffer_put_string(m, reply.data, reply.length);
                   if (client_user)
                           xfree(client_user);
                   if (reply.length)
                           xfree(reply.data);
           }
           mm_request_send(socket, MONITOR_ANS_KRB5, m);
   
           return success;
   }
   #endif
   
   int
 mm_answer_term(int socket, Buffer *req)  mm_answer_term(int socket, Buffer *req)
 {  {
         extern struct monitor *monitor;          extern struct monitor *pmonitor;
         int res, status;          int res, status;
   
         debug3("%s: tearing down sessions", __FUNCTION__);          debug3("%s: tearing down sessions", __func__);
   
         /* The child is terminating */          /* The child is terminating */
         session_destroy_all(&mm_session_close);          session_destroy_all(&mm_session_close);
   
         while (waitpid(monitor->m_pid, &status, 0) == -1)          while (waitpid(pmonitor->m_pid, &status, 0) == -1)
                 if (errno != EINTR)                  if (errno != EINTR)
                         exit(1);                          exit(1);
   
Line 1214 
Line 1361 
 }  }
   
 void  void
 monitor_apply_keystate(struct monitor *monitor)  monitor_apply_keystate(struct monitor *pmonitor)
 {  {
         if (compat20) {          if (compat20) {
                 set_newkeys(MODE_IN);                  set_newkeys(MODE_IN);
                 set_newkeys(MODE_OUT);                  set_newkeys(MODE_OUT);
         } else {          } else {
                 u_char key[SSH_SESSION_KEY_LENGTH];  
   
                 memset(key, 'a', sizeof(key));  
                 packet_set_protocol_flags(child_state.ssh1protoflags);                  packet_set_protocol_flags(child_state.ssh1protoflags);
                 packet_set_encryption_key(key, SSH_SESSION_KEY_LENGTH,                  packet_set_encryption_key(child_state.ssh1key,
                     child_state.ssh1cipher);                      child_state.ssh1keylen, child_state.ssh1cipher);
                   xfree(child_state.ssh1key);
         }          }
   
           /* for rc4 and other stateful ciphers */
         packet_set_keycontext(MODE_OUT, child_state.keyout);          packet_set_keycontext(MODE_OUT, child_state.keyout);
         xfree(child_state.keyout);          xfree(child_state.keyout);
         packet_set_keycontext(MODE_IN, child_state.keyin);          packet_set_keycontext(MODE_IN, child_state.keyin);
Line 1246 
Line 1392 
             sizeof(outgoing_stream));              sizeof(outgoing_stream));
   
         /* Update with new address */          /* Update with new address */
         mm_init_compression(monitor->m_zlib);          if (options.compression)
                   mm_init_compression(pmonitor->m_zlib);
   
         /* Network I/O buffers */          /* Network I/O buffers */
         /* XXX inefficient for large buffers, need: buffer_init_from_string */          /* XXX inefficient for large buffers, need: buffer_init_from_string */
Line 1271 
Line 1418 
         kex = xmalloc(sizeof(*kex));          kex = xmalloc(sizeof(*kex));
         memset(kex, 0, sizeof(*kex));          memset(kex, 0, sizeof(*kex));
         kex->session_id = buffer_get_string(m, &kex->session_id_len);          kex->session_id = buffer_get_string(m, &kex->session_id_len);
           if ((session_id2 == NULL) ||
               (kex->session_id_len != session_id2_len) ||
               (memcmp(kex->session_id, session_id2, session_id2_len) != 0))
                   fatal("mm_get_get: internal error: bad session id");
         kex->we_need = buffer_get_int(m);          kex->we_need = buffer_get_int(m);
         kex->server = 1;          kex->server = 1;
         kex->hostkey_type = buffer_get_int(m);          kex->hostkey_type = buffer_get_int(m);
Line 1296 
Line 1447 
 /* This function requries careful sanity checking */  /* This function requries careful sanity checking */
   
 void  void
 mm_get_keystate(struct monitor *monitor)  mm_get_keystate(struct monitor *pmonitor)
 {  {
         Buffer m;          Buffer m;
         u_char *blob, *p;          u_char *blob, *p;
         u_int bloblen, plen;          u_int bloblen, plen;
   
         debug3("%s: Waiting for new keys", __FUNCTION__);          debug3("%s: Waiting for new keys", __func__);
   
         buffer_init(&m);          buffer_init(&m);
         mm_request_receive_expect(monitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);          mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
         if (!compat20) {          if (!compat20) {
                 child_state.ssh1protoflags = buffer_get_int(&m);                  child_state.ssh1protoflags = buffer_get_int(&m);
                 child_state.ssh1cipher = buffer_get_int(&m);                  child_state.ssh1cipher = buffer_get_int(&m);
                   child_state.ssh1key = buffer_get_string(&m,
                       &child_state.ssh1keylen);
                 child_state.ivout = buffer_get_string(&m,                  child_state.ivout = buffer_get_string(&m,
                     &child_state.ivoutlen);                      &child_state.ivoutlen);
                 child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);                  child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
                 goto skip;                  goto skip;
         } else {          } else {
                 /* Get the Kex for rekeying */                  /* Get the Kex for rekeying */
                 *monitor->m_pkex = mm_get_kex(&m);                  *pmonitor->m_pkex = mm_get_kex(&m);
         }          }
   
         blob = buffer_get_string(&m, &bloblen);          blob = buffer_get_string(&m, &bloblen);
         current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);          current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
         xfree(blob);          xfree(blob);
   
         debug3("%s: Waiting for second key", __FUNCTION__);          debug3("%s: Waiting for second key", __func__);
         blob = buffer_get_string(&m, &bloblen);          blob = buffer_get_string(&m, &bloblen);
         current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);          current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
         xfree(blob);          xfree(blob);
Line 1336 
Line 1489 
         child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);          child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
         child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);          child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);
   
         debug3("%s: Getting compression state", __FUNCTION__);          debug3("%s: Getting compression state", __func__);
         /* Get compression state */          /* Get compression state */
         p = buffer_get_string(&m, &plen);          p = buffer_get_string(&m, &plen);
         if (plen != sizeof(child_state.outgoing))          if (plen != sizeof(child_state.outgoing))
                 fatal("%s: bad request size", __FUNCTION__);                  fatal("%s: bad request size", __func__);
         memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));          memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
         xfree(p);          xfree(p);
   
         p = buffer_get_string(&m, &plen);          p = buffer_get_string(&m, &plen);
         if (plen != sizeof(child_state.incoming))          if (plen != sizeof(child_state.incoming))
                 fatal("%s: bad request size", __FUNCTION__);                  fatal("%s: bad request size", __func__);
         memcpy(&child_state.incoming, p, sizeof(child_state.incoming));          memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
         xfree(p);          xfree(p);
   
         /* Network I/O buffers */          /* Network I/O buffers */
         debug3("%s: Getting Network I/O buffers", __FUNCTION__);          debug3("%s: Getting Network I/O buffers", __func__);
         child_state.input = buffer_get_string(&m, &child_state.ilen);          child_state.input = buffer_get_string(&m, &child_state.ilen);
         child_state.output = buffer_get_string(&m, &child_state.olen);          child_state.output = buffer_get_string(&m, &child_state.olen);
   
Line 1363 
Line 1516 
 void *  void *
 mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)  mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
 {  {
           size_t len = size * ncount;
         void *address;          void *address;
   
         address = mm_malloc(mm, size * ncount);          if (len == 0 || ncount > SIZE_T_MAX / size)
                   fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);
   
           address = mm_malloc(mm, len);
   
         return (address);          return (address);
 }  }
   
Line 1399 
Line 1556 
 monitor_socketpair(int *pair)  monitor_socketpair(int *pair)
 {  {
         if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)          if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
                 fatal("%s: socketpair", __FUNCTION__);                  fatal("%s: socketpair", __func__);
         FD_CLOSEONEXEC(pair[0]);          FD_CLOSEONEXEC(pair[0]);
         FD_CLOSEONEXEC(pair[1]);          FD_CLOSEONEXEC(pair[1]);
 }  }
Line 1420 
Line 1577 
         mon->m_sendfd = pair[1];          mon->m_sendfd = pair[1];
   
         /* Used to share zlib space across processes */          /* Used to share zlib space across processes */
         mon->m_zback = mm_create(NULL, MM_MEMSIZE);          if (options.compression) {
         mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);                  mon->m_zback = mm_create(NULL, MM_MEMSIZE);
                   mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
   
         /* Compression needs to share state across borders */                  /* Compression needs to share state across borders */
         mm_init_compression(mon->m_zlib);                  mm_init_compression(mon->m_zlib);
           }
   
         return mon;          return mon;
 }  }

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.9.2.4