summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-05-31 11:20:11 +1000
committerDamien Miller <djm@mindrot.org>2000-05-31 11:20:11 +1000
commit2f6a0ad191af2e0e67c66bdc5dfc84d9a97bf12c (patch)
tree3b25cc3ba9ed2ae288e33ee8dee5042cc4734020
parent03934f2eefc991f2a0be253be8869cf8f39758bc (diff)
- Cleanup of auth.c, login.c and fake-*
- Cleanup of auth-pam.c, save and print "account expired" error messages
-rw-r--r--ChangeLog4
-rw-r--r--auth-pam.c113
-rw-r--r--auth.c8
-rw-r--r--fake-getaddrinfo.c171
-rw-r--r--fake-getnameinfo.c76
-rw-r--r--fake-getnameinfo.h1
-rw-r--r--fake-socket.h10
-rw-r--r--login.c137
8 files changed, 274 insertions, 246 deletions
diff --git a/ChangeLog b/ChangeLog
index 0fb51014f..2899a4c4c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
120000531
2 - Cleanup of auth.c, login.c and fake-*
3 - Cleanup of auth-pam.c, save and print "account expired" error messages
4
120000530 520000530
2 - Define atexit for old Solaris 6 - Define atexit for old Solaris
3 - Fix buffer overrun in login.c for systems which use syslen in utmpx. 7 - Fix buffer overrun in login.c for systems which use syslen in utmpx.
diff --git a/auth-pam.c b/auth-pam.c
index e3f4c4252..174d289f3 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -13,12 +13,16 @@
13#include "xmalloc.h" 13#include "xmalloc.h"
14#include "servconf.h" 14#include "servconf.h"
15 15
16RCSID("$Id: auth-pam.c,v 1.4 2000/04/29 14:47:29 damien Exp $"); 16RCSID("$Id: auth-pam.c,v 1.5 2000/05/31 01:20:12 damien Exp $");
17
18#define NEW_AUTHTOK_MSG \
19 "Warning: You password has expired, please change it now"
17 20
18/* Callbacks */ 21/* Callbacks */
19static int pamconv(int num_msg, const struct pam_message **msg, 22static int pamconv(int num_msg, const struct pam_message **msg,
20 struct pam_response **resp, void *appdata_ptr); 23 struct pam_response **resp, void *appdata_ptr);
21void pam_cleanup_proc(void *context); 24void pam_cleanup_proc(void *context);
25void pam_msg_cat(const char *msg);
22 26
23/* module-local variables */ 27/* module-local variables */
24static struct pam_conv conv = { 28static struct pam_conv conv = {
@@ -27,7 +31,7 @@ static struct pam_conv conv = {
27}; 31};
28static struct pam_handle_t *pamh = NULL; 32static struct pam_handle_t *pamh = NULL;
29static const char *pampasswd = NULL; 33static const char *pampasswd = NULL;
30static char *pamconv_msg = NULL; 34static char *pam_msg = NULL;
31 35
32/* PAM conversation function. This is really a kludge to get the password */ 36/* PAM conversation function. This is really a kludge to get the password */
33/* into PAM and to pick up any messages generated by PAM into pamconv_msg */ 37/* into PAM and to pick up any messages generated by PAM into pamconv_msg */
@@ -36,8 +40,6 @@ static int pamconv(int num_msg, const struct pam_message **msg,
36{ 40{
37 struct pam_response *reply; 41 struct pam_response *reply;
38 int count; 42 int count;
39 size_t msg_len;
40 char *p;
41 43
42 /* PAM will free this later */ 44 /* PAM will free this later */
43 reply = malloc(num_msg * sizeof(*reply)); 45 reply = malloc(num_msg * sizeof(*reply));
@@ -54,31 +56,14 @@ static int pamconv(int num_msg, const struct pam_message **msg,
54 reply[count].resp_retcode = PAM_SUCCESS; 56 reply[count].resp_retcode = PAM_SUCCESS;
55 reply[count].resp = xstrdup(pampasswd); 57 reply[count].resp = xstrdup(pampasswd);
56 break; 58 break;
57
58 case PAM_TEXT_INFO: 59 case PAM_TEXT_INFO:
59 reply[count].resp_retcode = PAM_SUCCESS; 60 reply[count].resp_retcode = PAM_SUCCESS;
60 reply[count].resp = xstrdup(""); 61 reply[count].resp = xstrdup("");
61 62
62 if (msg[count]->msg == NULL) 63 if (msg[count]->msg != NULL)
63 break; 64 pam_msg_cat(msg[count]->msg);
64 65
65 debug("Adding PAM message: %s", msg[count]->msg);
66
67 msg_len = strlen(msg[count]->msg);
68 if (pamconv_msg) {
69 size_t n = strlen(pamconv_msg);
70 pamconv_msg = xrealloc(pamconv_msg, n + msg_len + 2);
71 p = pamconv_msg + n;
72 } else {
73 pamconv_msg = p = xmalloc(msg_len + 2);
74 }
75 memcpy(p, msg[count]->msg, msg_len);
76 p[msg_len] = '\n';
77 p[msg_len + 1] = '\0';
78 break; 66 break;
79
80 case PAM_PROMPT_ECHO_ON:
81 case PAM_ERROR_MSG:
82 default: 67 default:
83 free(reply); 68 free(reply);
84 return PAM_CONV_ERR; 69 return PAM_CONV_ERR;
@@ -100,19 +85,19 @@ void pam_cleanup_proc(void *context)
100 pam_retval = pam_close_session((pam_handle_t *)pamh, 0); 85 pam_retval = pam_close_session((pam_handle_t *)pamh, 0);
101 if (pam_retval != PAM_SUCCESS) { 86 if (pam_retval != PAM_SUCCESS) {
102 log("Cannot close PAM session: %.200s", 87 log("Cannot close PAM session: %.200s",
103 PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 88 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
104 } 89 }
105 90
106 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED); 91 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED);
107 if (pam_retval != PAM_SUCCESS) { 92 if (pam_retval != PAM_SUCCESS) {
108 log("Cannot delete credentials: %.200s", 93 log("Cannot delete credentials: %.200s",
109 PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 94 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
110 } 95 }
111 96
112 pam_retval = pam_end((pam_handle_t *)pamh, pam_retval); 97 pam_retval = pam_end((pam_handle_t *)pamh, pam_retval);
113 if (pam_retval != PAM_SUCCESS) { 98 if (pam_retval != PAM_SUCCESS) {
114 log("Cannot release PAM authentication: %.200s", 99 log("Cannot release PAM authentication: %.200s",
115 PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 100 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
116 } 101 }
117 } 102 }
118} 103}
@@ -135,7 +120,8 @@ int auth_pam_password(struct passwd *pw, const char *password)
135 120
136 pam_retval = pam_authenticate((pam_handle_t *)pamh, 0); 121 pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
137 if (pam_retval == PAM_SUCCESS) { 122 if (pam_retval == PAM_SUCCESS) {
138 debug("PAM Password authentication accepted for user \"%.100s\"", pw->pw_name); 123 debug("PAM Password authentication accepted for user \"%.100s\"",
124 pw->pw_name);
139 return 1; 125 return 1;
140 } else { 126 } else {
141 debug("PAM Password authentication for \"%.100s\" failed: %s", 127 debug("PAM Password authentication for \"%.100s\" failed: %s",
@@ -148,26 +134,36 @@ int auth_pam_password(struct passwd *pw, const char *password)
148int do_pam_account(char *username, char *remote_user) 134int do_pam_account(char *username, char *remote_user)
149{ 135{
150 int pam_retval; 136 int pam_retval;
151 137
152 debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname()); 138 debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname());
153 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST, 139 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST,
154 get_canonical_hostname()); 140 get_canonical_hostname());
155 if (pam_retval != PAM_SUCCESS) { 141 if (pam_retval != PAM_SUCCESS) {
156 fatal("PAM set rhost failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 142 fatal("PAM set rhost failed: %.200s",
143 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
157 } 144 }
158 145
159 if (remote_user != NULL) { 146 if (remote_user != NULL) {
160 debug("PAM setting ruser to \"%.200s\"", remote_user); 147 debug("PAM setting ruser to \"%.200s\"", remote_user);
161 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user); 148 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user);
162 if (pam_retval != PAM_SUCCESS) { 149 if (pam_retval != PAM_SUCCESS) {
163 fatal("PAM set ruser failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 150 fatal("PAM set ruser failed: %.200s",
151 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
164 } 152 }
165 } 153 }
166 154
167 pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0); 155 pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0);
168 if (pam_retval != PAM_SUCCESS) { 156 switch (pam_retval) {
169 log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 157 case PAM_SUCCESS:
170 return(0); 158 /* This is what we want */
159 break;
160 case PAM_NEW_AUTHTOK_REQD:
161 pam_msg_cat(NEW_AUTHTOK_MSG);
162 break;
163 default:
164 log("PAM rejected by account configuration: %.200s",
165 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
166 return(0);
171 } 167 }
172 168
173 return(1); 169 return(1);
@@ -181,13 +177,17 @@ void do_pam_session(char *username, const char *ttyname)
181 if (ttyname != NULL) { 177 if (ttyname != NULL) {
182 debug("PAM setting tty to \"%.200s\"", ttyname); 178 debug("PAM setting tty to \"%.200s\"", ttyname);
183 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname); 179 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname);
184 if (pam_retval != PAM_SUCCESS) 180 if (pam_retval != PAM_SUCCESS) {
185 fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 181 fatal("PAM set tty failed: %.200s",
182 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
183 }
186 } 184 }
187 185
188 pam_retval = pam_open_session((pam_handle_t *)pamh, 0); 186 pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
189 if (pam_retval != PAM_SUCCESS) 187 if (pam_retval != PAM_SUCCESS) {
190 fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 188 fatal("PAM session setup failed: %.200s",
189 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
190 }
191} 191}
192 192
193/* Set PAM credentials */ 193/* Set PAM credentials */
@@ -197,8 +197,10 @@ void do_pam_setcred()
197 197
198 debug("PAM establishing creds"); 198 debug("PAM establishing creds");
199 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED); 199 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED);
200 if (pam_retval != PAM_SUCCESS) 200 if (pam_retval != PAM_SUCCESS) {
201 fatal("PAM setcred failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); 201 fatal("PAM setcred failed: %.200s",
202 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
203 }
202} 204}
203 205
204/* Cleanly shutdown PAM */ 206/* Cleanly shutdown PAM */
@@ -217,9 +219,12 @@ void start_pam(struct passwd *pw)
217 219
218 pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, 220 pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv,
219 (pam_handle_t**)&pamh); 221 (pam_handle_t**)&pamh);
220 if (pam_retval != PAM_SUCCESS)
221 fatal("PAM initialisation failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
222 222
223 if (pam_retval != PAM_SUCCESS) {
224 fatal("PAM initialisation failed: %.200s",
225 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
226 }
227
223 fatal_add_cleanup(&pam_cleanup_proc, NULL); 228 fatal_add_cleanup(&pam_cleanup_proc, NULL);
224} 229}
225 230
@@ -237,8 +242,30 @@ char **fetch_pam_environment(void)
237/* or account checking to stderr */ 242/* or account checking to stderr */
238void print_pam_messages(void) 243void print_pam_messages(void)
239{ 244{
240 if (pamconv_msg != NULL) 245 if (pam_msg != NULL)
241 fprintf(stderr, pamconv_msg); 246 fprintf(stderr, pam_msg);
247}
248
249/* Append a message to the PAM message buffer */
250void pam_msg_cat(const char *msg)
251{
252 char *p;
253 size_t new_msg_len;
254 size_t pam_msg_len;
255
256 new_msg_len = strlen(msg);
257
258 if (pam_msg) {
259 pam_msg_len = strlen(pam_msg);
260 pam_msg = xrealloc(pam_msg, new_msg_len + pam_msg_len + 2);
261 p = pam_msg + pam_msg_len;
262 } else {
263 pam_msg = p = xmalloc(new_msg_len + 2);
264 }
265
266 memcpy(p, msg, new_msg_len);
267 p[new_msg_len] = '\n';
268 p[new_msg_len + 1] = '\0';
242} 269}
243 270
244#endif /* USE_PAM */ 271#endif /* USE_PAM */
diff --git a/auth.c b/auth.c
index 0a58df58b..685b8bb35 100644
--- a/auth.c
+++ b/auth.c
@@ -121,17 +121,17 @@ allowed_user(struct passwd * pw)
121 } 121 }
122 122
123#ifdef WITH_AIXAUTHENTICATE 123#ifdef WITH_AIXAUTHENTICATE
124 if (loginrestrictions(pw->pw_name,S_RLOGIN,NULL,&loginmsg) != 0) { 124 if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
125 if (loginmsg && *loginmsg) { 125 if (loginmsg && *loginmsg) {
126 /* Remove embedded newlines (if any) */ 126 /* Remove embedded newlines (if any) */
127 char *p; 127 char *p;
128 for (p = loginmsg; *p; p++) 128 for (p = loginmsg; *p; p++) {
129 if (*p == '\n') 129 if (*p == '\n')
130 *p = ' '; 130 *p = ' ';
131 }
131 /* Remove trailing newline */ 132 /* Remove trailing newline */
132 *--p = '\0'; 133 *--p = '\0';
133 log("Login restricted for %s: %.100s", 134 log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
134 pw->pw_name, loginmsg);
135 } 135 }
136 return 0; 136 return 0;
137 } 137 }
diff --git a/fake-getaddrinfo.c b/fake-getaddrinfo.c
index 456c41e58..b3af4aa2e 100644
--- a/fake-getaddrinfo.c
+++ b/fake-getaddrinfo.c
@@ -7,113 +7,112 @@
7 * But these functions are not implemented correctly. The minimum subset 7 * But these functions are not implemented correctly. The minimum subset
8 * is implemented for ssh use only. For exapmle, this routine assumes 8 * is implemented for ssh use only. For exapmle, this routine assumes
9 * that ai_family is AF_INET. Don't use it for another purpose. 9 * that ai_family is AF_INET. Don't use it for another purpose.
10 *
11 * In the case not using 'configure --enable-ipv6', this getaddrinfo.c
12 * will be used if you have broken getaddrinfo or no getaddrinfo.
13 */ 10 */
14 11
15#include "includes.h" 12#include "includes.h"
16#include "ssh.h" 13#include "ssh.h"
17 14
18#ifndef HAVE_GAI_STRERROR 15#ifndef HAVE_GAI_STRERROR
19char * 16char *gai_strerror(int ecode)
20gai_strerror(ecode)
21int ecode;
22{ 17{
23 switch (ecode) { 18 switch (ecode) {
24 case EAI_NODATA: 19 case EAI_NODATA:
25 return "no address associated with hostname."; 20 return "no address associated with hostname.";
26 case EAI_MEMORY: 21 case EAI_MEMORY:
27 return "memory allocation failure."; 22 return "memory allocation failure.";
28 default: 23 default:
29 return "unknown error."; 24 return "unknown error.";
30 } 25 }
31} 26}
32#endif /* !HAVE_GAI_STRERROR */ 27#endif /* !HAVE_GAI_STRERROR */
33 28
34#ifndef HAVE_FREEADDRINFO 29#ifndef HAVE_FREEADDRINFO
35void 30void freeaddrinfo(struct addrinfo *ai)
36freeaddrinfo(ai)
37struct addrinfo *ai;
38{ 31{
39 struct addrinfo *next; 32 struct addrinfo *next;
40 33
41 do { 34 do {
42 next = ai->ai_next; 35 next = ai->ai_next;
43 free(ai); 36 free(ai);
44 } while (NULL != (ai = next)); 37 } while (NULL != (ai = next));
45} 38}
46#endif /* !HAVE_FREEADDRINFO */ 39#endif /* !HAVE_FREEADDRINFO */
47 40
48#ifndef HAVE_GETADDRINFO 41#ifndef HAVE_GETADDRINFO
49static struct addrinfo * 42static struct addrinfo *malloc_ai(int port, u_long addr)
50malloc_ai(port, addr)
51int port;
52u_long addr;
53{ 43{
54 struct addrinfo *ai; 44 struct addrinfo *ai;
45
46 ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
47 if (ai == NULL)
48 return(NULL);
49
50 memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
51
52 ai->ai_addr = (struct sockaddr *)(ai + 1);
53 /* XXX -- ssh doesn't use sa_len */
54 ai->ai_addrlen = sizeof(struct sockaddr_in);
55 ai->ai_addr->sa_family = ai->ai_family = AF_INET;
55 56
56 if (NULL != (ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + 57 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
57 sizeof(struct sockaddr_in)))) { 58 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
58 memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); 59
59 ai->ai_addr = (struct sockaddr *)(ai + 1); 60 return(ai);
60 /* XXX -- ssh doesn't use sa_len */
61 ai->ai_addrlen = sizeof(struct sockaddr_in);
62 ai->ai_addr->sa_family = ai->ai_family = AF_INET;
63 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
64 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
65 return ai;
66 } else {
67 return NULL;
68 }
69} 61}
70 62
71int 63int getaddrinfo(const char *hostname, const char *servname,
72getaddrinfo(hostname, servname, hints, res) 64 const struct addrinfo *hints, struct addrinfo **res)
73const char *hostname, *servname;
74const struct addrinfo *hints;
75struct addrinfo **res;
76{ 65{
77 struct addrinfo *cur, *prev = NULL; 66 struct addrinfo *cur, *prev = NULL;
78 struct hostent *hp; 67 struct hostent *hp;
79 int i, port; 68 int i, port;
80 69
81 if (servname) 70 if (servname)
82 port = htons(atoi(servname)); 71 port = htons(atoi(servname));
83 else
84 port = 0;
85 if (hints && hints->ai_flags & AI_PASSIVE)
86 if (NULL != (*res = malloc_ai(port, htonl(0x00000000))))
87 return 0;
88 else
89 return EAI_MEMORY;
90 if (!hostname)
91 if (NULL != (*res = malloc_ai(port, htonl(0x7f000001))))
92 return 0;
93 else
94 return EAI_MEMORY;
95 if (inet_addr(hostname) != -1)
96 if (NULL != (*res = malloc_ai(port, inet_addr(hostname))))
97 return 0;
98 else
99 return EAI_MEMORY;
100 if ((hp = gethostbyname(hostname)) &&
101 hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
102 for (i = 0; hp->h_addr_list[i]; i++)
103 if (NULL != (cur = malloc_ai(port,
104 ((struct in_addr *)hp->h_addr_list[i])->s_addr))) {
105 if (prev)
106 prev->ai_next = cur;
107 else 72 else
108 *res = cur; 73 port = 0;
109 prev = cur; 74
110 } else { 75 if (hints && hints->ai_flags & AI_PASSIVE) {
111 if (*res) 76 if (NULL != (*res = malloc_ai(port, htonl(0x00000000))))
112 freeaddrinfo(*res); 77 return 0;
113 return EAI_MEMORY; 78 else
114 } 79 return EAI_MEMORY;
115 return 0; 80 }
116 } 81
117 return EAI_NODATA; 82 if (!hostname) {
83 if (NULL != (*res = malloc_ai(port, htonl(0x7f000001))))
84 return 0;
85 else
86 return EAI_MEMORY;
87 }
88
89 if (inet_addr(hostname) != -1) {
90 if (NULL != (*res = malloc_ai(port, inet_addr(hostname))))
91 return 0;
92 else
93 return EAI_MEMORY;
94 }
95
96 hp = gethostbyname(hostname);
97 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
98 for (i = 0; hp->h_addr_list[i]; i++) {
99 cur = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
100 if (cur == NULL) {
101 if (*res)
102 freeaddrinfo(*res);
103 return EAI_MEMORY;
104 }
105
106 if (prev)
107 prev->ai_next = cur;
108 else
109 *res = cur;
110
111 prev = cur;
112 }
113 return 0;
114 }
115
116 return EAI_NODATA;
118} 117}
119#endif /* !HAVE_GETADDRINFO */ 118#endif /* !HAVE_GETADDRINFO */
diff --git a/fake-getnameinfo.c b/fake-getnameinfo.c
index f74f3128f..867cf90b5 100644
--- a/fake-getnameinfo.c
+++ b/fake-getnameinfo.c
@@ -7,55 +7,47 @@
7 * But these functions are not implemented correctly. The minimum subset 7 * But these functions are not implemented correctly. The minimum subset
8 * is implemented for ssh use only. For exapmle, this routine assumes 8 * is implemented for ssh use only. For exapmle, this routine assumes
9 * that ai_family is AF_INET. Don't use it for another purpose. 9 * that ai_family is AF_INET. Don't use it for another purpose.
10 *
11 * In the case not using 'configure --enable-ipv6', this getnameinfo.c
12 * will be used if you have broken getnameinfo or no getnameinfo.
13 */ 10 */
14 11
15#include "includes.h" 12#include "includes.h"
16#include "ssh.h" 13#include "ssh.h"
17 14
18#ifndef HAVE_GETNAMEINFO 15#ifndef HAVE_GETNAMEINFO
19int 16int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
20getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) 17 size_t hostlen, char *serv, size_t servlen, int flags)
21const struct sockaddr *sa;
22size_t salen;
23char *host;
24size_t hostlen;
25char *serv;
26size_t servlen;
27int flags;
28{ 18{
29 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 19 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
30 struct hostent *hp; 20 struct hostent *hp;
31 char tmpserv[16]; 21 char tmpserv[16];
32 22
33 if (serv) { 23 if (serv) {
34 sprintf(tmpserv, "%d", ntohs(sin->sin_port)); 24 snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
35 if (strlen(tmpserv) > servlen) 25 if (strlen(tmpserv) > servlen)
36 return EAI_MEMORY; 26 return EAI_MEMORY;
37 else 27 else
38 strcpy(serv, tmpserv); 28 strcpy(serv, tmpserv);
39 }
40 if (host)
41 if (flags & NI_NUMERICHOST)
42 if (strlen(inet_ntoa(sin->sin_addr)) > hostlen)
43 return EAI_MEMORY;
44 else {
45 strcpy(host, inet_ntoa(sin->sin_addr));
46 return 0;
47 }
48 else
49 if (NULL != (hp = gethostbyaddr((char *)&sin->sin_addr,
50 sizeof(struct in_addr), AF_INET)))
51 if (strlen(hp->h_name) > hostlen)
52 return EAI_MEMORY;
53 else {
54 strcpy(host, hp->h_name);
55 return 0;
56 } 29 }
57 else 30
58 return EAI_NODATA; 31 if (host) {
59 return 0; 32 if (flags & NI_NUMERICHOST) {
33 if (strlen(inet_ntoa(sin->sin_addr)) > hostlen)
34 return EAI_MEMORY;
35
36 strcpy(host, inet_ntoa(sin->sin_addr));
37 return 0;
38 } else {
39 hp = gethostbyaddr((char *)&sin->sin_addr,
40 sizeof(struct in_addr), AF_INET);
41 if (hp == NULL)
42 return EAI_NODATA;
43
44 if (strlen(hp->h_name) > hostlen)
45 return EAI_MEMORY;
46
47 strcpy(host, hp->h_name);
48 return 0;
49 }
50 }
51 return 0;
60} 52}
61#endif /* !HAVE_GETNAMEINFO */ 53#endif /* !HAVE_GETNAMEINFO */
diff --git a/fake-getnameinfo.h b/fake-getnameinfo.h
index ecf0df2cf..0d25f4270 100644
--- a/fake-getnameinfo.h
+++ b/fake-getnameinfo.h
@@ -2,6 +2,7 @@
2#define _FAKE_GETNAMEINFO_H 2#define _FAKE_GETNAMEINFO_H
3 3
4#include "config.h" 4#include "config.h"
5
5#ifndef HAVE_GETNAMEINFO 6#ifndef HAVE_GETNAMEINFO
6int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 7int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
7 size_t hostlen, char *serv, size_t servlen, int flags); 8 size_t hostlen, char *serv, size_t servlen, int flags);
diff --git a/fake-socket.h b/fake-socket.h
index e11ad44e0..0e1624d11 100644
--- a/fake-socket.h
+++ b/fake-socket.h
@@ -5,10 +5,10 @@
5#include "sys/types.h" 5#include "sys/types.h"
6 6
7#ifndef HAVE_STRUCT_SOCKADDR_STORAGE 7#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
8#define _SS_MAXSIZE 128 /* Implementation specific max size */ 8# define _SS_MAXSIZE 128 /* Implementation specific max size */
9#define _SS_ALIGNSIZE (sizeof(int)) 9# define _SS_ALIGNSIZE (sizeof(int))
10#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(u_short)) 10# define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(u_short))
11#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof(u_short) + \ 11# define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof(u_short) + \
12 _SS_PAD1SIZE + _SS_ALIGNSIZE)) 12 _SS_PAD1SIZE + _SS_ALIGNSIZE))
13 13
14struct sockaddr_storage { 14struct sockaddr_storage {
@@ -20,7 +20,7 @@ struct sockaddr_storage {
20#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ 20#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
21 21
22#ifndef IN6_IS_ADDR_LOOPBACK 22#ifndef IN6_IS_ADDR_LOOPBACK
23#define IN6_IS_ADDR_LOOPBACK(a) \ 23# define IN6_IS_ADDR_LOOPBACK(a) \
24 (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ 24 (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
25 ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) 25 ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
26#endif /* !IN6_IS_ADDR_LOOPBACK */ 26#endif /* !IN6_IS_ADDR_LOOPBACK */
diff --git a/login.c b/login.c
index 6749a1556..6fdc71e68 100644
--- a/login.c
+++ b/login.c
@@ -18,7 +18,7 @@
18 */ 18 */
19 19
20#include "includes.h" 20#include "includes.h"
21RCSID("$Id: login.c,v 1.28 2000/05/30 03:12:46 damien Exp $"); 21RCSID("$Id: login.c,v 1.29 2000/05/31 01:20:12 damien Exp $");
22 22
23#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX) 23#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
24# include <utmpx.h> 24# include <utmpx.h>
@@ -38,6 +38,11 @@ RCSID("$Id: login.c,v 1.28 2000/05/30 03:12:46 damien Exp $");
38# include <login.h> 38# include <login.h>
39#endif 39#endif
40 40
41#ifdef WITH_AIXAUTHENTICATE
42/* This is done in do_authentication */
43# define DISABLE_LASTLOG
44#endif /* WITH_AIXAUTHENTICATE */
45
41/* 46/*
42 * Returns the time when the user last logged in. Returns 0 if the 47 * Returns the time when the user last logged in. Returns 0 if the
43 * information is not available. This must be called before record_login. 48 * information is not available. This must be called before record_login.
@@ -53,58 +58,50 @@ unsigned long
53get_last_login_time(uid_t uid, const char *logname, 58get_last_login_time(uid_t uid, const char *logname,
54 char *buf, unsigned int bufsize) 59 char *buf, unsigned int bufsize)
55{ 60{
56#if defined(WITH_AIXAUTHENTICATE)
57 /* This is done in do_authentication */
58 return (unsigned long) 0;
59#else
60#if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) 61#if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG)
61 struct lastlog ll; 62 struct lastlog ll;
62 char *lastlog;
63 int fd; 63 int fd;
64#ifdef LASTLOG_IS_DIR 64# ifdef LASTLOG_IS_DIR
65 char lbuf[1024]; 65 char lbuf[1024];
66#endif /* LASTLOG_IS_DIR */
67 66
68 lastlog = _PATH_LASTLOG; 67 snprintf(lbuf, sizeof(buf), "%s/%s", _PATH_LASTLOG, logname);
68 if ((fd = open(lbuf, O_RDONLY)) < 0)
69 return 0;
70# else /* LASTLOG_IS_DIR */
69 buf[0] = '\0'; 71 buf[0] = '\0';
70 72
71#ifndef LASTLOG_IS_DIR 73 if ((fd = open(_PATH_LASTLOG, O_RDONLY)) < 0)
72 fd = open(lastlog, O_RDONLY);
73 if (fd < 0)
74 return 0; 74 return 0;
75
75 lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET); 76 lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
76#else /* LASTLOG_IS_DIR */ 77# endif /* LASTLOG_IS_DIR */
77 snprintf(lbuf, sizeof(buf), "%s/%s", lastlog, logname);
78 fd = open(lbuf, O_RDONLY);
79 if (fd < 0)
80 return 0;
81#endif /* LASTLOG_IS_DIR */
82 if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) { 78 if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) {
83 close(fd); 79 close(fd);
84 return 0; 80 return 0;
85 } 81 }
82
86 close(fd); 83 close(fd);
84
87 if (bufsize > sizeof(ll.ll_host) + 1) 85 if (bufsize > sizeof(ll.ll_host) + 1)
88 bufsize = sizeof(ll.ll_host) + 1; 86 bufsize = sizeof(ll.ll_host) + 1;
89 strncpy(buf, ll.ll_host, bufsize - 1); 87 strncpy(buf, ll.ll_host, bufsize - 1);
90 buf[bufsize - 1] = 0; 88 buf[bufsize - 1] = 0;
91 return ll.ll_time;
92 89
90 return ll.ll_time;
93#else /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */ 91#else /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
94# ifdef HAVE_TYPE_IN_UTMP 92# ifdef HAVE_TYPE_IN_UTMP
95 /* Look in wtmp for the last login */ 93 /* Look in wtmp for the last login */
96 struct utmp wt; 94 struct utmp wt;
97 char *wt_file = _PATH_WTMP; 95 int fd1;
98 int fd1;
99 unsigned long t = 0; 96 unsigned long t = 0;
100 97
101 if ( (fd1 = open(wt_file, O_RDONLY)) < 0 ) { 98 if ((fd1 = open(_PATH_WTMP, O_RDONLY)) < 0) {
102 error("Couldn't open %.100s to find last login time.", wt_file); 99 error("Couldn't open %.100s to find last login time.", _PATH_WTMP);
103 return 0; 100 return 0;
104 } 101 }
105 102
106 /* seek to last record of file */ 103 /* seek to last record of file */
107 lseek(fd1, (off_t)(0-sizeof(struct utmp)), SEEK_END); 104 lseek(fd1, (off_t)(0 - sizeof(struct utmp)), SEEK_END);
108 105
109 /* loop through wtmp for our last user login record */ 106 /* loop through wtmp for our last user login record */
110 do { 107 do {
@@ -113,47 +110,44 @@ get_last_login_time(uid_t uid, const char *logname,
113 return 0; 110 return 0;
114 } 111 }
115 112
116 if ( wt.ut_type == USER_PROCESS) { 113 if (wt.ut_type == USER_PROCESS) {
117 if ( !strncmp(logname, wt.ut_user, 8) ) { 114 if (!strncmp(logname, wt.ut_user, 8)) {
118 t = (unsigned long) wt.ut_time; 115 t = (unsigned long)wt.ut_time;
119# ifdef HAVE_HOST_IN_UTMP 116# ifdef HAVE_HOST_IN_UTMP
120 if (bufsize > sizeof(wt.ut_host) + 1) 117 if (bufsize > sizeof(wt.ut_host) + 1)
121 bufsize = sizeof(wt.ut_host) + 1; 118 bufsize = sizeof(wt.ut_host) + 1;
122 strncpy(buf, wt.ut_host, bufsize - 1); 119 strncpy(buf, wt.ut_host, bufsize - 1);
123 buf[bufsize - 1] = 0; 120 buf[bufsize - 1] = 0;
124# else /* HAVE_HOST_IN_UTMP */ 121# else /* HAVE_HOST_IN_UTMP */
125 buf[0] = 0; 122 buf[0] = 0;
126# endif /* HAVE_HOST_IN_UTMP */ 123# endif /* HAVE_HOST_IN_UTMP */
127 } 124 }
128 } 125 }
129 126
130 if (lseek(fd1, (off_t)(0-2*sizeof(struct utmp)), SEEK_CUR) == -1) 127 if (lseek(fd1, (off_t)(0 - (2 * sizeof(struct utmp))), SEEK_CUR) < 0)
131 break; 128 break;
132 } while (t == 0); 129 } while (t == 0);
133 130
134 return t; 131 return t;
135# else 132# else /* HAVE_TYPE_IN_UTMP */
136 return 0; 133 return 0;
137# endif /* HAVE_TYPE_IN_UTMP */ 134# endif /* HAVE_TYPE_IN_UTMP */
138#endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */ 135#endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
139#endif /* defined(WITH_AIXAUTHENTICATE) */
140} 136}
141 137
142/* 138/*
143 * Records that the user has logged in. I these parts of operating systems 139 * Records that the user has logged in. I wish these parts of operating
144 * were more standardized. 140 * systems were more standardized.
145 */ 141 */
146
147void 142void
148record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid, 143record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
149 const char *host, struct sockaddr * addr) 144 const char *host, struct sockaddr * addr)
150{ 145{
151#if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) 146#if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG)
152 struct lastlog ll; 147 struct lastlog ll;
153 char *lastlog; 148# ifdef LASTLOG_IS_DIR
154#ifdef LASTLOG_IS_DIR
155 char buf[1024]; 149 char buf[1024];
156#endif /* LASTLOG_IS_DIR */ 150# endif /* LASTLOG_IS_DIR */
157#endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */ 151#endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
158 struct utmp u; 152 struct utmp u;
159#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX) 153#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
@@ -163,28 +157,35 @@ record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
163 /* Construct an utmp/wtmp entry. */ 157 /* Construct an utmp/wtmp entry. */
164 memset(&u, 0, sizeof(u)); 158 memset(&u, 0, sizeof(u));
165 strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line)); 159 strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
160
166#if defined(HAVE_ID_IN_UTMP) 161#if defined(HAVE_ID_IN_UTMP)
167#ifdef _AIX 162# ifdef _AIX
168 strncpy(u.ut_id, ttyname + 5, sizeof(u.ut_id)); 163 strncpy(u.ut_id, ttyname + 5, sizeof(u.ut_id));
169#else /* !AIX */ 164# else /* !AIX */
170 strncpy(u.ut_id, ttyname + 8, sizeof(u.ut_id)); 165 strncpy(u.ut_id, ttyname + 8, sizeof(u.ut_id));
171#endif 166# endif
172#endif /* defined(HAVE_ID_IN_UTMP) */ 167#endif /* defined(HAVE_ID_IN_UTMP) */
168
173 strncpy(u.ut_name, user, sizeof(u.ut_name)); 169 strncpy(u.ut_name, user, sizeof(u.ut_name));
170
174#if defined(HAVE_TV_IN_UTMP) 171#if defined(HAVE_TV_IN_UTMP)
175 (void)gettimeofday(&u.ut_tv, NULL); 172 (void)gettimeofday(&u.ut_tv, NULL);
176#else /* defined(HAVE_TV_IN_UTMP) */ 173#else /* defined(HAVE_TV_IN_UTMP) */
177 u.ut_time = time(NULL); 174 u.ut_time = time(NULL);
178#endif /* defined(HAVE_TV_IN_UTMP) */ 175#endif /* defined(HAVE_TV_IN_UTMP) */
176
179#if defined(HAVE_PID_IN_UTMP) 177#if defined(HAVE_PID_IN_UTMP)
180 u.ut_pid = (pid_t)pid; 178 u.ut_pid = (pid_t)pid;
181#endif /* HAVE_PID_IN_UTMP */ 179#endif /* HAVE_PID_IN_UTMP */
180
182#if defined(HAVE_TYPE_IN_UTMP) 181#if defined(HAVE_TYPE_IN_UTMP)
183 u.ut_type = (uid == -1)?DEAD_PROCESS:USER_PROCESS; 182 u.ut_type = (uid == -1)?DEAD_PROCESS:USER_PROCESS;
184#endif /* HAVE_TYPE_IN_UTMP */ 183#endif /* HAVE_TYPE_IN_UTMP */
184
185#if defined(HAVE_HOST_IN_UTMP) 185#if defined(HAVE_HOST_IN_UTMP)
186 strncpy(u.ut_host, host, sizeof(u.ut_host)); 186 strncpy(u.ut_host, host, sizeof(u.ut_host));
187#endif 187#endif
188
188#if defined(HAVE_ADDR_IN_UTMP) 189#if defined(HAVE_ADDR_IN_UTMP)
189 if (addr) { 190 if (addr) {
190 switch (addr->sa_family) { 191 switch (addr->sa_family) {
@@ -193,26 +194,29 @@ record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
193 memcpy(&(u.ut_addr), &(in->sin_addr), sizeof(&(in->sin_addr))); 194 memcpy(&(u.ut_addr), &(in->sin_addr), sizeof(&(in->sin_addr)));
194 break; 195 break;
195 } 196 }
196#if defined(HAVE_ADDR_V6_IN_UTMP) 197# if defined(HAVE_ADDR_V6_IN_UTMP)
197 case AF_INET6: { 198 case AF_INET6: {
198 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; 199 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
199 memcpy(u.ut_addr_v6, &(in6->sin6_addr), sizeof(&(in6->sin6_addr))); 200 memcpy(u.ut_addr_v6, &(in6->sin6_addr), sizeof(&(in6->sin6_addr)));
200 break; 201 break;
201 } 202 }
202#endif 203# endif /* defined(HAVE_ADDR_V6_IN_UTMP) */
203 default: 204 default:
204 break; 205 break;
205 } 206 }
206 } 207 }
207#endif 208#endif /* defined(HAVE_ADDR_IN_UTMP) */
208 209
209#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX) 210#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
210 memset(&utx, 0, sizeof(utx)); 211 memset(&utx, 0, sizeof(utx));
212
211 strncpy(utx.ut_user, user, sizeof(utx.ut_name)); 213 strncpy(utx.ut_user, user, sizeof(utx.ut_name));
212 strncpy(utx.ut_line, ttyname + 5, sizeof(utx.ut_line)); 214 strncpy(utx.ut_line, ttyname + 5, sizeof(utx.ut_line));
213 strncpy(utx.ut_id, ttyname + 8, sizeof(utx.ut_id)); 215 strncpy(utx.ut_id, ttyname + 8, sizeof(utx.ut_id));
216
214 utx.ut_pid = (pid_t)pid; 217 utx.ut_pid = (pid_t)pid;
215 (void)gettimeofday(&utx.ut_tv, NULL); 218 (void)gettimeofday(&utx.ut_tv, NULL);
219
216 utx.ut_type = (uid == -1)?DEAD_PROCESS:USER_PROCESS; 220 utx.ut_type = (uid == -1)?DEAD_PROCESS:USER_PROCESS;
217# ifdef HAVE_HOST_IN_UTMPX 221# ifdef HAVE_HOST_IN_UTMPX
218# ifdef HAVE_SYSLEN_IN_UTMPX 222# ifdef HAVE_SYSLEN_IN_UTMPX
@@ -225,7 +229,8 @@ record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
225# endif /* HAVE_SYSLEN_IN_UTMPX */ 229# endif /* HAVE_SYSLEN_IN_UTMPX */
226 utx.ut_host[sizeof(utx.ut_host)-1] = '\0'; 230 utx.ut_host[sizeof(utx.ut_host)-1] = '\0';
227# endif 231# endif
228#if defined(HAVE_ADDR_IN_UTMPX) 232
233# if defined(HAVE_ADDR_IN_UTMPX)
229 if (addr) { 234 if (addr) {
230 switch (addr->sa_family) { 235 switch (addr->sa_family) {
231 case AF_INET: { 236 case AF_INET: {
@@ -233,31 +238,27 @@ record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
233 memcpy(&(utx.ut_addr), &(in->sin_addr), sizeof(&(in->sin_addr))); 238 memcpy(&(utx.ut_addr), &(in->sin_addr), sizeof(&(in->sin_addr)));
234 break; 239 break;
235 } 240 }
236#if defined(HAVE_ADDR_V6_IN_UTMPX) 241# if defined(HAVE_ADDR_V6_IN_UTMPX)
237 case AF_INET6: { 242 case AF_INET6: {
238 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; 243 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
239 memcpy(utx.ut_addr_v6, &(in6->sin6_addr), sizeof(&(in6->sin6_addr))); 244 memcpy(utx.ut_addr_v6, &(in6->sin6_addr), sizeof(&(in6->sin6_addr)));
240 break; 245 break;
241 } 246 }
242#endif 247# endif /* defined(HAVE_ADDR_V6_IN_UTMPX) */
243 default: 248 default:
244 break; 249 break;
245 } 250 }
246 } 251 }
247#endif 252# endif /* defined(HAVE_ADDR_IN_UTMPX) */
248#endif /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */ 253#endif /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */
249 254
250/*#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX) && !defined(HAVE_LOGIN)*/
251#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX) 255#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
252 login(&u, &utx); 256 login(&u, &utx);
253#else /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */ 257#else /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */
254 login(&u); 258 login(&u);
255#endif /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */ 259#endif /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */
256 260
257#if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) && !defined(WITH_AIXAUTHENTICATE) 261#if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG)
258 /* AIX does this in do_authentication */
259 lastlog = _PATH_LASTLOG;
260
261 /* Update lastlog unless actually recording a logout. */ 262 /* Update lastlog unless actually recording a logout. */
262 if (strcmp(user, "") != 0) { 263 if (strcmp(user, "") != 0) {
263 int fd; 264 int fd;
@@ -271,21 +272,25 @@ record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
271 ll.ll_time = time(NULL); 272 ll.ll_time = time(NULL);
272 strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line)); 273 strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
273 strncpy(ll.ll_host, host, sizeof(ll.ll_host)); 274 strncpy(ll.ll_host, host, sizeof(ll.ll_host));
274#ifdef LASTLOG_IS_DIR 275# ifdef LASTLOG_IS_DIR
275 snprintf(buf, sizeof(buf), "%s/%s", lastlog, user); 276 snprintf(buf, sizeof(buf), "%s/%s", _PATH_LASTLOG, user);
276 fd = open(buf, O_RDWR); 277 if ((fd = open(buf, O_RDWR)) >= 0) {
277 if (fd >= 0) {
278#else /* LASTLOG_IS_DIR */
279 fd = open(lastlog, O_RDWR);
280 if (fd >= 0) {
281 lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
282#endif /* LASTLOG_IS_DIR */
283 if (write(fd, &ll, sizeof(ll)) != sizeof(ll)) 278 if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
284 log("Could not write %.100s: %.100s", lastlog, strerror(errno)); 279 log("Could not write %.100s: %.100s", buf, strerror(errno));
285 close(fd); 280 close(fd);
286 } 281 }
282# else /* LASTLOG_IS_DIR */
283 if ((fd = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
284 lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
285 if (write(fd, &ll, sizeof(ll)) != sizeof(ll)) {
286 log("Could not write %.100s: %.100s", _PATH_LASTLOG,
287 strerror(errno));
288 }
289 close(fd);
290 }
291# endif /* LASTLOG_IS_DIR */
287 } 292 }
288#endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) && !defined(WITH_AIXAUTHENTICATE) */ 293#endif /* defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG) */
289} 294}
290 295
291/* Records that the user has logged out. */ 296/* Records that the user has logged out. */