xref: /freebsd/crypto/openssh/openbsd-compat/port-aix.c (revision efcad6b72fe9d4f7ea99c021f4903d09ca31b666)
14b17dab0SDag-Erling Smørgrav /*
24b17dab0SDag-Erling Smørgrav  *
34b17dab0SDag-Erling Smørgrav  * Copyright (c) 2001 Gert Doering.  All rights reserved.
44b17dab0SDag-Erling Smørgrav  *
54b17dab0SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
64b17dab0SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
74b17dab0SDag-Erling Smørgrav  * are met:
84b17dab0SDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
94b17dab0SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
104b17dab0SDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
114b17dab0SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
124b17dab0SDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
134b17dab0SDag-Erling Smørgrav  *
144b17dab0SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
154b17dab0SDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
164b17dab0SDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
174b17dab0SDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
184b17dab0SDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
194b17dab0SDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
204b17dab0SDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
214b17dab0SDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
224b17dab0SDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
234b17dab0SDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
244b17dab0SDag-Erling Smørgrav  *
254b17dab0SDag-Erling Smørgrav  */
2683d2307dSDag-Erling Smørgrav #include "includes.h"
27efcad6b7SDag-Erling Smørgrav #include "auth.h"
28d95e11bfSDag-Erling Smørgrav #include "ssh.h"
29d95e11bfSDag-Erling Smørgrav #include "log.h"
30d95e11bfSDag-Erling Smørgrav #include "servconf.h"
31d95e11bfSDag-Erling Smørgrav #include "canohost.h"
32d95e11bfSDag-Erling Smørgrav #include "xmalloc.h"
33efcad6b7SDag-Erling Smørgrav #include "buffer.h"
3483d2307dSDag-Erling Smørgrav 
3583d2307dSDag-Erling Smørgrav #ifdef _AIX
3683d2307dSDag-Erling Smørgrav 
3783d2307dSDag-Erling Smørgrav #include <uinfo.h>
38d95e11bfSDag-Erling Smørgrav #include "port-aix.h"
39d95e11bfSDag-Erling Smørgrav 
40d95e11bfSDag-Erling Smørgrav extern ServerOptions options;
41efcad6b7SDag-Erling Smørgrav extern Buffer loginmsg;
42efcad6b7SDag-Erling Smørgrav 
43efcad6b7SDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB
44efcad6b7SDag-Erling Smørgrav static char old_registry[REGISTRY_SIZE] = "";
45efcad6b7SDag-Erling Smørgrav # endif
4683d2307dSDag-Erling Smørgrav 
4783d2307dSDag-Erling Smørgrav /*
484b17dab0SDag-Erling Smørgrav  * AIX has a "usrinfo" area where logname and other stuff is stored -
494b17dab0SDag-Erling Smørgrav  * a few applications actually use this and die if it's not set
504b17dab0SDag-Erling Smørgrav  *
514b17dab0SDag-Erling Smørgrav  * NOTE: TTY= should be set, but since no one uses it and it's hard to
524b17dab0SDag-Erling Smørgrav  * acquire due to privsep code.  We will just drop support.
5383d2307dSDag-Erling Smørgrav  */
5483d2307dSDag-Erling Smørgrav void
554b17dab0SDag-Erling Smørgrav aix_usrinfo(struct passwd *pw)
5683d2307dSDag-Erling Smørgrav {
5783d2307dSDag-Erling Smørgrav 	u_int i;
58d95e11bfSDag-Erling Smørgrav 	size_t len;
594b17dab0SDag-Erling Smørgrav 	char *cp;
6083d2307dSDag-Erling Smørgrav 
61d95e11bfSDag-Erling Smørgrav 	len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name));
62d95e11bfSDag-Erling Smørgrav 	cp = xmalloc(len);
63d95e11bfSDag-Erling Smørgrav 
64d95e11bfSDag-Erling Smørgrav 	i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0',
65d95e11bfSDag-Erling Smørgrav 	    pw->pw_name, '\0');
6683d2307dSDag-Erling Smørgrav 	if (usrinfo(SETUINFO, cp, i) == -1)
6783d2307dSDag-Erling Smørgrav 		fatal("Couldn't set usrinfo: %s", strerror(errno));
6883d2307dSDag-Erling Smørgrav 	debug3("AIX/UsrInfo: set len %d", i);
69d95e11bfSDag-Erling Smørgrav 
7083d2307dSDag-Erling Smørgrav 	xfree(cp);
7183d2307dSDag-Erling Smørgrav }
7283d2307dSDag-Erling Smørgrav 
73d95e11bfSDag-Erling Smørgrav # ifdef WITH_AIXAUTHENTICATE
74d95e11bfSDag-Erling Smørgrav /*
75d95e11bfSDag-Erling Smørgrav  * Remove embedded newlines in string (if any).
76d95e11bfSDag-Erling Smørgrav  * Used before logging messages returned by AIX authentication functions
77d95e11bfSDag-Erling Smørgrav  * so the message is logged on one line.
78d95e11bfSDag-Erling Smørgrav  */
79d95e11bfSDag-Erling Smørgrav void
80d95e11bfSDag-Erling Smørgrav aix_remove_embedded_newlines(char *p)
81d95e11bfSDag-Erling Smørgrav {
82d95e11bfSDag-Erling Smørgrav 	if (p == NULL)
83d95e11bfSDag-Erling Smørgrav 		return;
84d95e11bfSDag-Erling Smørgrav 
85d95e11bfSDag-Erling Smørgrav 	for (; *p; p++) {
86d95e11bfSDag-Erling Smørgrav 		if (*p == '\n')
87d95e11bfSDag-Erling Smørgrav 			*p = ' ';
88d95e11bfSDag-Erling Smørgrav 	}
89d95e11bfSDag-Erling Smørgrav 	/* Remove trailing whitespace */
90d95e11bfSDag-Erling Smørgrav 	if (*--p == ' ')
91d95e11bfSDag-Erling Smørgrav 		*p = '\0';
92d95e11bfSDag-Erling Smørgrav }
93efcad6b7SDag-Erling Smørgrav 
94efcad6b7SDag-Erling Smørgrav /*
95efcad6b7SDag-Erling Smørgrav  * Do authentication via AIX's authenticate routine.  We loop until the
96efcad6b7SDag-Erling Smørgrav  * reenter parameter is 0, but normally authenticate is called only once.
97efcad6b7SDag-Erling Smørgrav  *
98efcad6b7SDag-Erling Smørgrav  * Note: this function returns 1 on success, whereas AIX's authenticate()
99efcad6b7SDag-Erling Smørgrav  * returns 0.
100efcad6b7SDag-Erling Smørgrav  */
101efcad6b7SDag-Erling Smørgrav int
102efcad6b7SDag-Erling Smørgrav sys_auth_passwd(Authctxt *ctxt, const char *password)
103efcad6b7SDag-Erling Smørgrav {
104efcad6b7SDag-Erling Smørgrav 	char *authmsg = NULL, *host, *msg, *name = ctxt->pw->pw_name;
105efcad6b7SDag-Erling Smørgrav 	int authsuccess = 0, expired, reenter, result;
106efcad6b7SDag-Erling Smørgrav 
107efcad6b7SDag-Erling Smørgrav 	do {
108efcad6b7SDag-Erling Smørgrav 		result = authenticate((char *)name, (char *)password, &reenter,
109efcad6b7SDag-Erling Smørgrav 		    &authmsg);
110efcad6b7SDag-Erling Smørgrav 		aix_remove_embedded_newlines(authmsg);
111efcad6b7SDag-Erling Smørgrav 		debug3("AIX/authenticate result %d, msg %.100s", result,
112efcad6b7SDag-Erling Smørgrav 		    authmsg);
113efcad6b7SDag-Erling Smørgrav 	} while (reenter);
114efcad6b7SDag-Erling Smørgrav 
115efcad6b7SDag-Erling Smørgrav 	if (result == 0) {
116efcad6b7SDag-Erling Smørgrav 		authsuccess = 1;
117efcad6b7SDag-Erling Smørgrav 
118efcad6b7SDag-Erling Smørgrav 		host = (char *)get_canonical_hostname(options.use_dns);
119efcad6b7SDag-Erling Smørgrav 
120efcad6b7SDag-Erling Smørgrav 	       	/*
121efcad6b7SDag-Erling Smørgrav 		 * Record successful login.  We don't have a pty yet, so just
122efcad6b7SDag-Erling Smørgrav 		 * label the line as "ssh"
123efcad6b7SDag-Erling Smørgrav 		 */
124efcad6b7SDag-Erling Smørgrav 		aix_setauthdb(name);
125efcad6b7SDag-Erling Smørgrav 	       	if (loginsuccess((char *)name, (char *)host, "ssh", &msg) == 0) {
126efcad6b7SDag-Erling Smørgrav 			if (msg != NULL) {
127efcad6b7SDag-Erling Smørgrav 				debug("%s: msg %s", __func__, msg);
128efcad6b7SDag-Erling Smørgrav 				buffer_append(&loginmsg, msg, strlen(msg));
129efcad6b7SDag-Erling Smørgrav 				xfree(msg);
130efcad6b7SDag-Erling Smørgrav 			}
131efcad6b7SDag-Erling Smørgrav 		}
132efcad6b7SDag-Erling Smørgrav 
133efcad6b7SDag-Erling Smørgrav 		/*
134efcad6b7SDag-Erling Smørgrav 		 * Check if the user's password is expired.
135efcad6b7SDag-Erling Smørgrav 		 */
136efcad6b7SDag-Erling Smørgrav                 expired = passwdexpired(name, &msg);
137efcad6b7SDag-Erling Smørgrav                 if (msg && *msg) {
138efcad6b7SDag-Erling Smørgrav                         buffer_append(&loginmsg, msg, strlen(msg));
139efcad6b7SDag-Erling Smørgrav                         aix_remove_embedded_newlines(msg);
140efcad6b7SDag-Erling Smørgrav                 }
141efcad6b7SDag-Erling Smørgrav                 debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg);
142efcad6b7SDag-Erling Smørgrav 
143efcad6b7SDag-Erling Smørgrav 		switch (expired) {
144efcad6b7SDag-Erling Smørgrav 		case 0: /* password not expired */
145efcad6b7SDag-Erling Smørgrav 			break;
146efcad6b7SDag-Erling Smørgrav 		case 1: /* expired, password change required */
147efcad6b7SDag-Erling Smørgrav 			ctxt->force_pwchange = 1;
148efcad6b7SDag-Erling Smørgrav 			disable_forwarding();
149efcad6b7SDag-Erling Smørgrav 			break;
150efcad6b7SDag-Erling Smørgrav 		default: /* user can't change(2) or other error (-1) */
151efcad6b7SDag-Erling Smørgrav 			logit("Password can't be changed for user %s: %.100s",
152efcad6b7SDag-Erling Smørgrav 			    name, msg);
153efcad6b7SDag-Erling Smørgrav 			if (msg)
154efcad6b7SDag-Erling Smørgrav 				xfree(msg);
155efcad6b7SDag-Erling Smørgrav 			authsuccess = 0;
156efcad6b7SDag-Erling Smørgrav 		}
157efcad6b7SDag-Erling Smørgrav 
158efcad6b7SDag-Erling Smørgrav 		aix_restoreauthdb();
159efcad6b7SDag-Erling Smørgrav 	}
160efcad6b7SDag-Erling Smørgrav 
161efcad6b7SDag-Erling Smørgrav 	if (authmsg != NULL)
162efcad6b7SDag-Erling Smørgrav 		xfree(authmsg);
163efcad6b7SDag-Erling Smørgrav 
164efcad6b7SDag-Erling Smørgrav 	return authsuccess;
165efcad6b7SDag-Erling Smørgrav }
166d95e11bfSDag-Erling Smørgrav 
167d95e11bfSDag-Erling Smørgrav #  ifdef CUSTOM_FAILED_LOGIN
168d95e11bfSDag-Erling Smørgrav /*
169d95e11bfSDag-Erling Smørgrav  * record_failed_login: generic "login failed" interface function
170d95e11bfSDag-Erling Smørgrav  */
171d95e11bfSDag-Erling Smørgrav void
172d95e11bfSDag-Erling Smørgrav record_failed_login(const char *user, const char *ttyname)
173d95e11bfSDag-Erling Smørgrav {
174efcad6b7SDag-Erling Smørgrav 	char *hostname = (char *)get_canonical_hostname(options.use_dns);
175d95e11bfSDag-Erling Smørgrav 
176d95e11bfSDag-Erling Smørgrav 	if (geteuid() != 0)
177d95e11bfSDag-Erling Smørgrav 		return;
178d95e11bfSDag-Erling Smørgrav 
179d95e11bfSDag-Erling Smørgrav 	aix_setauthdb(user);
180d95e11bfSDag-Erling Smørgrav #   ifdef AIX_LOGINFAILED_4ARG
181d95e11bfSDag-Erling Smørgrav 	loginfailed((char *)user, hostname, (char *)ttyname, AUDIT_FAIL_AUTH);
182d95e11bfSDag-Erling Smørgrav #   else
183d95e11bfSDag-Erling Smørgrav 	loginfailed((char *)user, hostname, (char *)ttyname);
184d95e11bfSDag-Erling Smørgrav #   endif
185efcad6b7SDag-Erling Smørgrav 	aix_restoreauthdb();
186d95e11bfSDag-Erling Smørgrav }
187efcad6b7SDag-Erling Smørgrav #  endif /* CUSTOM_FAILED_LOGIN */
188d95e11bfSDag-Erling Smørgrav 
189d95e11bfSDag-Erling Smørgrav /*
190d95e11bfSDag-Erling Smørgrav  * If we have setauthdb, retrieve the password registry for the user's
191efcad6b7SDag-Erling Smørgrav  * account then feed it to setauthdb.  This will mean that subsequent AIX auth
192efcad6b7SDag-Erling Smørgrav  * functions will only use the specified loadable module.  If we don't have
193efcad6b7SDag-Erling Smørgrav  * setauthdb this is a no-op.
194d95e11bfSDag-Erling Smørgrav  */
195d95e11bfSDag-Erling Smørgrav void
196d95e11bfSDag-Erling Smørgrav aix_setauthdb(const char *user)
197d95e11bfSDag-Erling Smørgrav {
198d95e11bfSDag-Erling Smørgrav #  ifdef HAVE_SETAUTHDB
199efcad6b7SDag-Erling Smørgrav 	char *registry;
200d95e11bfSDag-Erling Smørgrav 
201d95e11bfSDag-Erling Smørgrav 	if (setuserdb(S_READ) == -1) {
202d95e11bfSDag-Erling Smørgrav 		debug3("%s: Could not open userdb to read", __func__);
203d95e11bfSDag-Erling Smørgrav 		return;
204d95e11bfSDag-Erling Smørgrav 	}
205d95e11bfSDag-Erling Smørgrav 
206d95e11bfSDag-Erling Smørgrav 	if (getuserattr((char *)user, S_REGISTRY, &registry, SEC_CHAR) == 0) {
207efcad6b7SDag-Erling Smørgrav 		if (setauthdb(registry, old_registry) == 0)
208efcad6b7SDag-Erling Smørgrav 			debug3("AIX/setauthdb set registry '%s'", registry);
209d95e11bfSDag-Erling Smørgrav 		else
210efcad6b7SDag-Erling Smørgrav 			debug3("AIX/setauthdb set registry '%s' failed: %s",
211efcad6b7SDag-Erling Smørgrav 			    registry, strerror(errno));
212d95e11bfSDag-Erling Smørgrav 	} else
213d95e11bfSDag-Erling Smørgrav 		debug3("%s: Could not read S_REGISTRY for user: %s", __func__,
214d95e11bfSDag-Erling Smørgrav 		    strerror(errno));
215d95e11bfSDag-Erling Smørgrav 	enduserdb();
216efcad6b7SDag-Erling Smørgrav #  endif /* HAVE_SETAUTHDB */
217d95e11bfSDag-Erling Smørgrav }
21883d2307dSDag-Erling Smørgrav 
219efcad6b7SDag-Erling Smørgrav /*
220efcad6b7SDag-Erling Smørgrav  * Restore the user's registry settings from old_registry.
221efcad6b7SDag-Erling Smørgrav  * Note that if the first aix_setauthdb fails, setauthdb("") is still safe
222efcad6b7SDag-Erling Smørgrav  * (it restores the system default behaviour).  If we don't have setauthdb,
223efcad6b7SDag-Erling Smørgrav  * this is a no-op.
224efcad6b7SDag-Erling Smørgrav  */
225efcad6b7SDag-Erling Smørgrav void
226efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(void)
227efcad6b7SDag-Erling Smørgrav {
228efcad6b7SDag-Erling Smørgrav #  ifdef HAVE_SETAUTHDB
229efcad6b7SDag-Erling Smørgrav 	if (setauthdb(old_registry, NULL) == 0)
230efcad6b7SDag-Erling Smørgrav 		debug3("%s: restoring old registry '%s'", __func__,
231efcad6b7SDag-Erling Smørgrav 		    old_registry);
232efcad6b7SDag-Erling Smørgrav 	else
233efcad6b7SDag-Erling Smørgrav 		debug3("%s: failed to restore old registry %s", __func__,
234efcad6b7SDag-Erling Smørgrav 		    old_registry);
235efcad6b7SDag-Erling Smørgrav #  endif /* HAVE_SETAUTHDB */
236efcad6b7SDag-Erling Smørgrav }
237efcad6b7SDag-Erling Smørgrav 
238efcad6b7SDag-Erling Smørgrav # endif /* WITH_AIXAUTHENTICATE */
239efcad6b7SDag-Erling Smørgrav 
240efcad6b7SDag-Erling Smørgrav #endif /* _AIX */
241