--- cvs-1.11.23/src/server.c +++ cvs-1.11.23/src/server.c @@ -62,6 +62,11 @@ int cvs_gssapi_encrypt; #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI) #include +#include +#include + +static const char *remote_name (int fd); +static char *cvs_username; #endif #ifdef HAVE_SYSLOG_H @@ -72,7 +77,6 @@ int cvs_gssapi_encrypt; #endif #ifdef HAVE_KERBEROS -# include # include # ifndef HAVE_KRB_GET_ERR_TEXT # define krb_get_err_text(status) krb_err_txt[status] @@ -5417,12 +5421,9 @@ error 0 %s: no such system user\n", username); if (pw->pw_uid == 0) { #ifdef HAVE_SYSLOG_H - /* FIXME: Can the IP address of the connecting client be retrieved - * and printed here? - */ syslog (LOG_DAEMON | LOG_ALERT, - "attempt to root from account: %s", cvs_username - ); + "%s: ROOT LOGIN REJECTED for %s", + remote_name(0), cvs_username); #endif printf("error 0: root not allowed\n"); error_exit (); @@ -5576,6 +5577,10 @@ check_repository_password (username, password, repository, host_user_ptr) fp = CVS_FOPEN (filename, "r"); if (fp == NULL) { +#ifdef HAVE_SYSLOG_H + syslog (LOG_ERR, "%s: unable to open %s for reading: %m", + remote_name(0), filename); +#endif if (!existence_error (errno)) error (0, errno, "cannot open %s", filename); free (filename); @@ -5594,9 +5599,21 @@ check_repository_password (username, password, repository, host_user_ptr) } } if (ferror (fp)) + { +#ifdef HAVE_SYSLOG_H + syslog (LOG_ERR, "%s: error reading %s: %m", + remote_name(0), filename); +#endif error (0, errno, "cannot read %s", filename); + } if (fclose (fp) < 0) + { +#ifdef HAVE_SYSLOG_H + syslog (LOG_ERR, "%s: error closing %s[%d]: %m", + remote_name(0), filename, fileno(fp)); +#endif error (0, errno, "cannot close %s", filename); + } /* If found_it, then linebuf contains the information we need. */ if (found_it) @@ -5665,6 +5682,11 @@ check_repository_password (username, password, repository, host_user_ptr) || ((strcmp (found_password, crypt (password, found_password)) == 0))) { +#ifdef LOG_AUTHPRIV + syslog (LOG_AUTHPRIV | LOG_INFO, + "%s: password ok according to %s", + remote_name(0), filename); +#endif /* Give host_user_ptr permanent storage. */ *host_user_ptr = xstrdup (host_user_tmp); retval = 1; @@ -5672,9 +5694,9 @@ check_repository_password (username, password, repository, host_user_ptr) else { #ifdef LOG_AUTHPRIV - syslog (LOG_AUTHPRIV | LOG_NOTICE, - "password mismatch for %s in %s: %s vs. %s", username, - repository, crypt(password, found_password), found_password); + syslog (LOG_AUTHPRIV | LOG_NOTICE, + "%s: password incorrect according to %s", + remote_name(0), filename); #endif *host_user_ptr = NULL; retval = 2; @@ -5682,6 +5704,11 @@ check_repository_password (username, password, repository, host_user_ptr) } else /* Didn't find this user, so deny access. */ { +#ifdef LOG_AUTHPRIV + syslog (LOG_AUTHPRIV | LOG_NOTICE, + "%s: password not found according to %s", + remote_name(0), filename); +#endif *host_user_ptr = NULL; retval = 0; } @@ -5731,6 +5758,10 @@ check_password (username, password, repository) letting you in if it won't say why, and I am not convinced that the potential information disclosure to an attacker outweighs this. */ +#ifdef HAVE_SYSLOG_H + syslog (LOG_NOTICE, "%s: repository \"%s\" not allowed", + remote_name(0), repository); +#endif printf ("error 0 no such user %s in CVSROOT/passwd\n", username); error_exit (); @@ -5757,6 +5788,10 @@ check_password (username, password, repository) if (found_passwd == NULL) { +#ifdef LOG_AUTHPRIV + syslog (LOG_AUTHPRIV | LOG_NOTICE, "%s: user not found", + remote_name(0)); +#endif printf ("E Fatal error, aborting.\n\ error 0 %s: no such user\n", username); @@ -5784,14 +5819,17 @@ error 0 %s: no such user\n", username); if (strcmp (found_passwd, crypt (password, found_passwd)) == 0) { host_user = xstrdup (username); +#ifdef LOG_AUTHPRIV + syslog (LOG_AUTHPRIV | LOG_INFO, + "%s: password ok", remote_name(0)); +#endif } else { host_user = NULL; #ifdef LOG_AUTHPRIV syslog (LOG_AUTHPRIV | LOG_NOTICE, - "password mismatch for %s: %s vs. %s", username, - crypt(password, found_passwd), found_passwd); + "%s: password incorrect", remote_name(0)); #endif } goto handle_return; @@ -5802,24 +5840,33 @@ error 0 %s: no such user\n", username); /* user exists and has no system password, but we got one as parameter */ host_user = xstrdup (username); +#ifdef LOG_AUTHPRIV + syslog (LOG_AUTHPRIV | LOG_INFO, + "%s: unexpected password", remote_name(0)); +#endif goto handle_return; } /* user exists but has no password at all */ host_user = NULL; -#ifdef LOG_AUTHPRIV - syslog (LOG_AUTHPRIV | LOG_NOTICE, - "login refused for %s: user has no password", username); -#endif handle_return: if (host_user) { +#ifdef LOG_AUTHPRIV + syslog (LOG_AUTHPRIV | LOG_INFO, + "%s: access granted as %s", + remote_name(0), host_user); +#endif /* Set CVS_Username here, in allocated space. It might or might not be the same as host_user. */ CVS_Username = xmalloc (strlen (username) + 1); strcpy (CVS_Username, username); } +#ifdef LOG_AUTHPRIV + syslog (LOG_AUTHPRIV | LOG_INFO, + "%s: access denied", remote_name(0)); +#endif return host_user; } @@ -5828,6 +5875,29 @@ handle_return: #if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI) +const char *remote_name (int fd) +{ + struct sockaddr_in peer; + int len; + len = sizeof peer; + if (getpeername (fd, (struct sockaddr *) &peer, &len) < 0) + return "unknown"; + else + { + static char *message = NULL; + char *host = inet_ntoa (peer.sin_addr); + char port[1 + sizeof(unsigned int) * 3]; + + snprintf (port, sizeof(port), "%u", ntohs (peer.sin_port)); + + free (message); + if (cvs_username) + xasprintf (&message, "%s@%s:%s", cvs_username, host, port); + else + xasprintf (&message, "%s:%s", host, port); + return message; + } +} /* Read username and password from client (i.e., stdin). If correct, then switch to run as that user and send an ACK to the client via stdout, else send NACK and die. */ @@ -5891,6 +5961,11 @@ pserver_authenticate_connection () * big deal. */ +#ifdef HAVE_SYSLOG_H + openlog( "cvs_pserver", LOG_PID, LOG_DAEMON ); + syslog (LOG_INFO, "connection from %s", remote_name(0)); +#endif + #ifdef SO_KEEPALIVE /* Set SO_KEEPALIVE on the socket, so that we don't hang forever if the client dies while we are waiting for input. */ @@ -5911,7 +5986,12 @@ pserver_authenticate_connection () if (getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX) < 0) { #ifdef HAVE_SYSLOG_H - syslog (LOG_DAEMON | LOG_NOTICE, "bad auth protocol start: EOF"); + if (feof(stdin)) + syslog (LOG_INFO, "%s: EOF encountered on read", + remote_name(0) ); + else + syslog (LOG_INFO, "%s: error reading input: %m", + remote_name(0)); #endif error (1, 0, "bad auth protocol start: EOF"); } @@ -5931,7 +6011,13 @@ pserver_authenticate_connection () #endif } else + { +#ifdef HAVE_SYSLOG_H + syslog (LOG_NOTICE, "%s: bad auth protocol start: %s", + remote_name(0), tmp); +#endif error (1, 0, "bad auth protocol start: %s", tmp); + } #ifndef AUTH_SERVER_SUPPORT @@ -5964,13 +6050,20 @@ pserver_authenticate_connection () "END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n") != 0) { +#ifdef HAVE_SYSLOG_H + syslog (LOG_NOTICE, "%s: bad auth protocol end: %s", + remote_name(0), tmp); +#endif error (1, 0, "bad auth protocol end: %s", tmp); } + + cvs_username = xstrdup( username ); if (!root_allow_ok (repository)) { printf ("error 0 %s: no such repository\n", repository); #ifdef HAVE_SYSLOG_H - syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository); + syslog (LOG_DAEMON | LOG_NOTICE, "%s: login refused for %s", + remote_name(0), repository); #endif goto i_hate_you; } @@ -5988,7 +6081,8 @@ pserver_authenticate_connection () if (host_user == NULL) { #ifdef HAVE_SYSLOG_H - syslog (LOG_DAEMON | LOG_NOTICE, "login failure (for %s)", repository); + syslog (LOG_DAEMON | LOG_NOTICE, "%s: login failure (for %s)", + remote_name(0), repository); #endif memset (descrambled_password, 0, strlen (descrambled_password)); free (descrambled_password);