/*
*
* Copyright (c) 2001 Gert Doering. All rights reserved.
- * Copyright (c) 2003,2004 Darren Tucker. All rights reserved.
+ * Copyright (c) 2003,2004,2005,2006 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*
*/
#include "includes.h"
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "key.h"
+#include "hostfile.h"
#include "auth.h"
#include "ssh.h"
#include "log.h"
-#include "servconf.h"
-#include "canohost.h"
-#include "xmalloc.h"
-#include "buffer.h"
#ifdef _AIX
+#include <errno.h>
+#if defined(HAVE_NETDB_H)
+# include <netdb.h>
+#endif
#include <uinfo.h>
-#include "port-aix.h"
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#ifdef WITH_AIXAUTHENTICATE
+# include <login.h>
+# include <userpw.h>
+# if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG)
+# include <sys/audit.h>
+# endif
+# include <usersec.h>
+#endif
-extern ServerOptions options;
-extern Buffer loginmsg;
+#include "port-aix.h"
# ifdef HAVE_SETAUTHDB
static char old_registry[REGISTRY_SIZE] = "";
# endif
/*
- * AIX has a "usrinfo" area where logname and other stuff is stored -
+ * AIX has a "usrinfo" area where logname and other stuff is stored -
* a few applications actually use this and die if it's not set
*
* NOTE: TTY= should be set, but since no one uses it and it's hard to
len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name));
cp = xmalloc(len);
- i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0',
+ i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0',
pw->pw_name, '\0');
if (usrinfo(SETUINFO, cp, i) == -1)
fatal("Couldn't set usrinfo: %s", strerror(errno));
int
sys_auth_passwd(Authctxt *ctxt, const char *password)
{
- char *authmsg = NULL, *msg, *name = ctxt->pw->pw_name;
+ char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name;
int authsuccess = 0, expired, reenter, result;
do {
result = authenticate((char *)name, (char *)password, &reenter,
&authmsg);
aix_remove_embedded_newlines(authmsg);
- debug3("AIX/authenticate result %d, msg %.100s", result,
+ debug3("AIX/authenticate result %d, authmsg %.100s", result,
authmsg);
} while (reenter);
if (result == 0) {
authsuccess = 1;
- /*
+ /*
* Record successful login. We don't have a pty yet, so just
* label the line as "ssh"
*/
*/
expired = passwdexpired(name, &msg);
if (msg && *msg) {
- buffer_append(&loginmsg, msg, strlen(msg));
+ buffer_append(ctxt->loginmsg, msg, strlen(msg));
aix_remove_embedded_newlines(msg);
}
debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg);
break;
case 1: /* expired, password change required */
ctxt->force_pwchange = 1;
- disable_forwarding();
break;
default: /* user can't change(2) or other error (-1) */
logit("Password can't be changed for user %s: %.100s",
* Returns 1 if login is allowed, 0 if not allowed.
*/
int
-sys_auth_allowed_user(struct passwd *pw)
+sys_auth_allowed_user(struct passwd *pw, Buffer *loginmsg)
{
char *msg = NULL;
int result, permitted = 0;
/*
* Don't perform checks for root account (PermitRootLogin controls
- * logins via * ssh) or if running as non-root user (since
+ * logins via ssh) or if running as non-root user (since
* loginrestrictions will always fail due to insufficient privilege).
*/
if (pw->pw_uid == 0 || geteuid() != 0) {
if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0)
permitted = 1;
else if (msg != NULL)
- buffer_append(&loginmsg, msg, strlen(msg));
+ buffer_append(loginmsg, msg, strlen(msg));
if (msg == NULL)
msg = xstrdup("(none)");
aix_remove_embedded_newlines(msg);
}
int
-sys_auth_record_login(const char *user, const char *host, const char *ttynm)
+sys_auth_record_login(const char *user, const char *host, const char *ttynm,
+ Buffer *loginmsg)
{
- char *msg;
+ char *msg = NULL;
+ static int msg_done = 0;
int success = 0;
aix_setauthdb(user);
- if (loginsuccess((char *)user, host, ttynm, &msg) == 0) {
+ if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) {
success = 1;
- if (msg != NULL) {
- debug("AIX/loginsuccess: msg %s", __func__, msg);
- buffer_append(&loginmsg, msg, strlen(msg));
+ if (msg != NULL && loginmsg != NULL && !msg_done) {
+ debug("AIX/loginsuccess: msg %s", msg);
+ buffer_append(loginmsg, msg, strlen(msg));
xfree(msg);
+ msg_done = 1;
}
}
aix_restoreauthdb();
* record_failed_login: generic "login failed" interface function
*/
void
-record_failed_login(const char *user, const char *ttyname)
+record_failed_login(const char *user, const char *hostname, const char *ttyname)
{
- char *hostname = (char *)get_canonical_hostname(options.use_dns);
-
if (geteuid() != 0)
return;
aix_setauthdb(user);
# ifdef AIX_LOGINFAILED_4ARG
- loginfailed((char *)user, hostname, (char *)ttyname, AUDIT_FAIL_AUTH);
+ loginfailed((char *)user, (char *)hostname, (char *)ttyname,
+ AUDIT_FAIL_AUTH);
# else
- loginfailed((char *)user, hostname, (char *)ttyname);
+ loginfailed((char *)user, (char *)hostname, (char *)ttyname);
# endif
aix_restoreauthdb();
}
# endif /* WITH_AIXAUTHENTICATE */
+# if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO)
+# undef getnameinfo
+/*
+ * For some reason, AIX's getnameinfo will refuse to resolve the all-zeros
+ * IPv6 address into its textual representation ("::"), so we wrap it
+ * with a function that will.
+ */
+int
+sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags)
+{
+ struct sockaddr_in6 *sa6;
+ u_int32_t *a6;
+
+ if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) &&
+ sa->sa_family == AF_INET6) {
+ sa6 = (struct sockaddr_in6 *)sa;
+ a6 = sa6->sin6_addr.u6_addr.u6_addr32;
+
+ if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
+ strlcpy(host, "::", hostlen);
+ snprintf(serv, servlen, "%d", sa6->sin6_port);
+ return 0;
+ }
+ }
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+# endif /* AIX_GETNAMEINFO_HACK */
+
+# if defined(USE_GETGRSET)
+# include <stdlib.h>
+int
+getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt)
+{
+ char *cp, *grplist, *grp;
+ gid_t gid;
+ int ret = 0, ngroups = 0, maxgroups;
+ long l;
+
+ maxgroups = *grpcnt;
+
+ if ((cp = grplist = getgrset(user)) == NULL)
+ return -1;
+
+ /* handle zero-length case */
+ if (maxgroups <= 0) {
+ *grpcnt = 0;
+ return -1;
+ }
+
+ /* copy primary group */
+ groups[ngroups++] = pgid;
+
+ /* copy each entry from getgrset into group list */
+ while ((grp = strsep(&grplist, ",")) != NULL) {
+ l = strtol(grp, NULL, 10);
+ if (ngroups >= maxgroups || l == LONG_MIN || l == LONG_MAX) {
+ ret = -1;
+ goto out;
+ }
+ gid = (gid_t)l;
+ if (gid == pgid)
+ continue; /* we have already added primary gid */
+ groups[ngroups++] = gid;
+ }
+out:
+ free(cp);
+ *grpcnt = ngroups;
+ return ret;
+}
+# endif /* USE_GETGRSET */
+
#endif /* _AIX */