~ubuntu-branches/ubuntu/trusty/uucp/trusty

« back to all changes in this revision

Viewing changes to debian/contrib/in.uucpd.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Palfrader
  • Date: 2004-12-30 15:30:22 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20041230153022-mx4cdr9j3u9bldo3
Tags: 1.07-12
Add cs localisation for debconf templates (closes: #287305).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * uucpd.c      Designed to be run from inetd. Checks loginname/password,
 
3
 *              also checks if this _really_ is a uucp login.
 
4
 *              Does utmp/wtmp accounting.
 
5
 *
 
6
 * Version:     @(#)uucpd.c  1.00  19-May-1998  miquels@cistron.nl
 
7
 * Version:     @(#)uucpd.c  1.10  28-Jul-2001  alex@king.net.nz
 
8
 *
 
9
 */
 
10
#include <sys/types.h>
 
11
#include <stdio.h>
 
12
#include <errno.h>
 
13
#include <stdlib.h>
 
14
#include <unistd.h>
 
15
#include <string.h>
 
16
#include <signal.h>
 
17
#include <sys/wait.h>
 
18
#include <syslog.h>
 
19
#include <utmp.h>
 
20
#include <time.h>
 
21
 
 
22
#include <pwd.h>
 
23
#include <grp.h>
 
24
 
 
25
#include <security/pam_appl.h>
 
26
#include <security/pam_misc.h>
 
27
 
 
28
#include <sys/socket.h>
 
29
#include <netinet/in.h>
 
30
#include <arpa/inet.h>
 
31
#include <netdb.h>
 
32
 
 
33
int myconv(int n,const struct pam_message **msg, struct pam_response **resp, void *ap)
 
34
{
 
35
        int k,rv;
 
36
        char *cp;
 
37
 
 
38
        rv=misc_conv(n,msg,resp,ap);
 
39
        if (rv != PAM_SUCCESS)
 
40
                return rv;
 
41
        /* 
 
42
         * The supplied misc_conv function doesn't seem to strip the
 
43
         * trailing return character so I do it here...
 
44
         */
 
45
        for (k=0;k<n;k++)
 
46
                for (cp=((*resp)->resp);*cp!=0;cp++)
 
47
                        if (*cp=='\r') *cp=0;
 
48
        return PAM_SUCCESS;
 
49
}
 
50
 
 
51
static struct pam_conv conv = {
 
52
        myconv,
 
53
        NULL
 
54
};
 
55
 
 
56
void chop(char *s)
 
57
{
 
58
        char *p;
 
59
 
 
60
        for(p = s; *p; p++)
 
61
                if (*p == '\r' || *p == '\n') {
 
62
                        *p = 0;
 
63
                        break;
 
64
                }
 
65
}
 
66
 
 
67
 
 
68
/*
 
69
 *      Read one line from the input.
 
70
 */
 
71
int getstr(int fd, char *buf, int len)
 
72
{
 
73
        int i, n, cnt;
 
74
        int nlseen = 0;
 
75
 
 
76
        cnt = 0;
 
77
 
 
78
        while(!nlseen) {
 
79
                if ((n = read(fd, buf + cnt, len - cnt)) <= 0) {
 
80
                        if (n == -1 && errno == EINTR)
 
81
                                continue;
 
82
                        break;
 
83
                }
 
84
                cnt += n;
 
85
                for(i = 0; i < cnt; i++) {
 
86
                        if (buf[i] == '\r' || buf[i] == '\n') {
 
87
                                nlseen = 1;
 
88
                                break;
 
89
                        }
 
90
                }
 
91
                if (cnt >= len) break;
 
92
        }
 
93
 
 
94
        return cnt > 0 ? cnt : n;
 
95
}
 
96
 
 
97
 
 
98
int main(void)
 
99
{
 
100
        char login[UT_NAMESIZE];
 
101
        char host[UT_HOSTSIZE];
 
102
        struct passwd *pwd;
 
103
        char *s;
 
104
        struct sockaddr_in sin;
 
105
        int sinlen;
 
106
        struct hostent *h;
 
107
        struct utmp ut;
 
108
        pid_t pid;
 
109
        int st;
 
110
        int rv;
 
111
        pam_handle_t *pamh=NULL;
 
112
 
 
113
        /*
 
114
         *      Make sure we have fds 0, 1 and 2.
 
115
         */
 
116
        close(1);
 
117
        close(2);
 
118
        dup(0);
 
119
        dup(0);
 
120
        openlog("uucpd", LOG_PID, LOG_UUCP);
 
121
 
 
122
        /*
 
123
         *      Get the remote host address.
 
124
         */
 
125
        sinlen = sizeof(sin);
 
126
        if (getpeername(0, (struct sockaddr *)&sin, &sinlen) < 0) {
 
127
                syslog(LOG_ERR, "getpeername: %m");
 
128
                exit(1);
 
129
        }
 
130
        if ((h = gethostbyaddr((char *)&sin.sin_addr,
 
131
            sizeof(sin.sin_addr), AF_INET)) != NULL) {
 
132
                strncpy(host, h->h_name, sizeof(host));
 
133
                host[sizeof(host) - 1] = 0;
 
134
        } else
 
135
                strcpy(host, inet_ntoa(sin.sin_addr));
 
136
 
 
137
        login[0] = 0;
 
138
 
 
139
        alarm(60);
 
140
 
 
141
        while(1) {
 
142
                printf("login: ");
 
143
                fflush(stdout);
 
144
                if (getstr(0, login, sizeof(login)) < 0)
 
145
                        exit(1);
 
146
                login[sizeof(login) - 1] = 0;
 
147
                chop(login);
 
148
                if (login[0] != 0) break;
 
149
        }
 
150
 
 
151
        rv=pam_start("uucp",login,&conv,&pamh);
 
152
        if (rv==PAM_SUCCESS)
 
153
                rv=pam_authenticate(pamh, 0);
 
154
        if (rv==PAM_SUCCESS)
 
155
                rv=pam_set_item(pamh,PAM_RHOST,host);
 
156
        if (rv==PAM_SUCCESS) 
 
157
                rv=pam_acct_mgmt(pamh,0);
 
158
        if (rv!=PAM_SUCCESS) {
 
159
                syslog(LOG_AUTHPRIV|LOG_NOTICE,pam_strerror(pamh,rv));
 
160
                goto incorrect;
 
161
        }
 
162
        if ((pwd = getpwnam(login)) == NULL) {
 
163
incorrect:
 
164
                syslog(LOG_AUTHPRIV|LOG_NOTICE,
 
165
                        "invalid password for `%s' on `TCP' from `%s'",
 
166
                        login, host);
 
167
                printf("Login incorrect.\r\n");
 
168
                exit(1);
 
169
        }
 
170
 
 
171
        /*
 
172
         *      See if we have a valid shell: the basename must
 
173
         *      match uucico*
 
174
         *
 
175
         *      Note: arguably this check should be done by PAM, but
 
176
         *      an appropriate PAM module doesn't exist to my knowledge.
 
177
         */
 
178
        if ((s = strrchr(pwd->pw_shell, '/')) == NULL)
 
179
                s = pwd->pw_shell;
 
180
        else
 
181
                s++;
 
182
        if (strncmp(s, "uucico", 6) != 0) {
 
183
                syslog(LOG_AUTHPRIV|LOG_NOTICE,
 
184
                        "invalid shell for `%s' on `TCP' from `%s'",
 
185
                        login, host);
 
186
                printf("Invalid shell (not uucico)\r\n");
 
187
                exit(1);
 
188
        }
 
189
 
 
190
        /*
 
191
         *      Allright we can assume the rest will go OK.
 
192
         */
 
193
        memset(&ut, 0, sizeof(ut));
 
194
        ut.ut_type = LOGIN_PROCESS;
 
195
        strncpy(ut.ut_user, login, sizeof(ut.ut_user));
 
196
        strncpy(ut.ut_host, host, sizeof(ut.ut_host));
 
197
        ut.ut_addr = sin.sin_addr.s_addr;
 
198
        ut.ut_time = time(NULL);
 
199
 
 
200
        /*
 
201
         *      Fork, let the parent wait to write the utmp file.
 
202
         */
 
203
        signal(SIGHUP, SIG_IGN);
 
204
        if ((pid = fork()) != 0) {
 
205
 
 
206
                if (pid < 0) {
 
207
                        /* FIXME: SCREAM (oh well..) */
 
208
                        return 1;
 
209
                }
 
210
                pam_open_session(pamh, 0);
 
211
 
 
212
                ut.ut_pid = pid;
 
213
                sprintf(ut.ut_line, "uucp%d", ut.ut_pid);
 
214
                snprintf(ut.ut_id, sizeof(ut.ut_id), "uu%02x", ut.ut_pid&0xff);
 
215
                pututline(&ut);
 
216
                endutent();
 
217
                updwtmp(WTMP_FILE, &ut);
 
218
 
 
219
                while(wait(&st) != pid);
 
220
                        ;
 
221
 
 
222
                ut.ut_type = DEAD_PROCESS;
 
223
                ut.ut_time = time(NULL);
 
224
                ut.ut_user[0] = 0;
 
225
                pututline(&ut);
 
226
                endutent();
 
227
                updwtmp(WTMP_FILE, &ut);
 
228
                pam_close_session(pamh, 0);
 
229
                pam_end(pamh,PAM_SUCCESS);
 
230
 
 
231
                return 0;
 
232
        }
 
233
 
 
234
        /*
 
235
         *      This is the child - exec uucico.
 
236
         */
 
237
        signal(SIGHUP, SIG_DFL);
 
238
        if (chdir(pwd->pw_dir) != 0) {
 
239
                perror(pwd->pw_dir);
 
240
                exit(1);
 
241
        }
 
242
        if (setgid(pwd->pw_gid) != 0) {
 
243
                perror("setgid");
 
244
                exit(1);
 
245
        }
 
246
        if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
 
247
                perror("initgroups");
 
248
                exit(1);
 
249
        }
 
250
        if (setuid(pwd->pw_uid) != 0) {
 
251
                perror("setuid");
 
252
                exit(1);
 
253
        }
 
254
        setenv("LOGNAME", pwd->pw_name, 1);
 
255
        setenv("USER", pwd->pw_name, 1);
 
256
        setenv("SHELL", pwd->pw_shell, 1);
 
257
        setenv("TERM", "dumb", 1);
 
258
 
 
259
 
 
260
        execl(pwd->pw_shell, pwd->pw_shell, NULL);
 
261
 
 
262
        perror(pwd->pw_shell);
 
263
        return 1;
 
264
}
 
265