File: authvchkpw.c

package info (click to toggle)
courier-authlib 0.58-4%2Betch3
  • links: PTS
  • area: main
  • in suites: etch
  • size: 16,212 kB
  • ctags: 1,896
  • sloc: ansic: 21,550; sh: 14,071; makefile: 866; perl: 842; cpp: 284
file content (195 lines) | stat: -rw-r--r-- 5,073 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
** Copyright 1998 - 2004 Double Precision, Inc.  See COPYING for
** distribution information.
*/

#if	HAVE_CONFIG_H
#include	"courier_auth_config.h"
#endif
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<errno.h>
#include	<pwd.h>
#if	HAVE_UNISTD_H
#include	<unistd.h>
#endif
#include	"auth.h"
#include	"authstaticlist.h"
#include	"courierauthdebug.h"
#include	"vpopmail_config.h"
#include	<vpopmail.h>
#include	<vauth.h>

static const char rcsid[]="$Id: authvchkpw.c,v 1.25 2005/02/20 04:41:20 mrsam Exp $";

extern int auth_vchkpw_pre(const char *userid, const char *service,
        int (*callback)(struct authinfo *, void *),
                        void *arg);

extern FILE *authvchkpw_file(const char *, const char *);

struct callback_info {
	const char *pass;
	int (*callback_func)(struct authinfo *, void *);
	void *callback_arg;
	};

static int callback_vchkpw(struct authinfo *a, void *p)
{
struct callback_info *i=(struct callback_info *)p;

	/* exit with perm failure if the supplied password is empty,
	 * or if the supplied password doesnt match the retrieved password */ 
	if (a->passwd == 0)
	{
		DPRINTF("no password supplied");
		return (-1);
	}

	if (authcheckpassword(i->pass, a->passwd))
		return (-1);

	a->clearpasswd=i->pass;
	return (*i->callback_func)(a, i->callback_arg);
}

int auth_vchkpw(const char *service, const char *authtype, char *authdata,
	int (*callback_func)(struct authinfo *, void *), void *callback_arg)
{
char *user, *pass;
struct	callback_info	ci;
int	rc;
	/* Make sure that we have been supplied with the correct
	 * AUTHDATA format which is : userid<NEWLINE>password<NEWLINE>
	 */
	if (strcmp(authtype, AUTHTYPE_LOGIN) ||
		(user=strtok(authdata, "\n")) == 0 ||
		(pass=strtok(0, "\n")) == 0)
	{
		/* login syntax was invalid */
		errno=EPERM;
		return (-1);
	}

	ci.pass=pass;
	ci.callback_func=callback_func;
	ci.callback_arg=callback_arg;

	/* auth_vchkpw_pre() does this :
	 *   - lookup the passwd entry for this user from the auth backend
	 *   - check to see if this user is permitted to use this service type
	 * If successful it will populate the ci struct with the 
	 * user's passwd entry. Return value of function will be 0.
	 * If unsuccessful (eg user doesnt exist, or is not permitted to 
	 * use this auth method), it will return :
	 *  <0 on a permanent failure (eg user doesnt exist)
	 *  >0 on a temp failure
         */
	rc=auth_vchkpw_pre(user, service, &callback_vchkpw, &ci);

	if (rc)
		return rc;

	/* user has been successfully auth'ed at this point */

#if 0
	/*
	** sam - new courier-authlib never receives TCPREMOTEIP, at this
	** time.
	*/

#ifdef HAVE_OPEN_SMTP_RELAY
	if ( (strcmp("pop3", service)==0) || (strcmp("imap", service)==0) ) {
		/* Michael Bowe 13th August 2003
		 *
		 * There is a problem here because open_smtp_relay needs 
		 * to get the user's ip from getenv("TCPREMOTEIP").
		 * If we run --with-authvchkpw --without-authdaemon,
		 * then this var is available.
		 * But if we run --with-authvchkpw --with-authdaemon,
		 * then TCPREMOTEIP is null
		 * 
		 * If TCPREMOTEIP isnt available, then open_smtp_relay()
		 * will just return() back immediately.
		 */
		open_smtp_relay();
	}
#endif
#endif

	return 0;
}

static void authvchkpwclose()
{
}

static int auth_vchkpw_changepass(const char *service,
				  const char *username,
				  const char *pass,
				  const char *npass)
{
struct vqpasswd *vpw;
char	User[256];
char	Domain[256];

        /* Take the supplied userid, and split it out into the user and domain
         * parts. (If a domain was not supplied, then set the domain to be
         * the default domain)
         */
        /* WARNING: parse_email lowercases the username in place - not const!! */
        if ( parse_email(username, User, Domain, 256) != 0) {
                /* Failed to successfully extract user and domain.
                 * So now exit with a permanent failure code
                 */
                return(-1);
        }

	/* check to see if domain exists.
	 * If you pass an alias domain to vget_assign, it will change it
	 * to be the real domain on return from the function
	 */
        if ( vget_assign(Domain,NULL,0,NULL,NULL) ==NULL ) {
		/* domain doesnt exist */
		return (-1);
	}

        if ( (vpw=vauth_getpw(User, Domain)) == NULL) {
		/* That user doesnt exist in the auth backend */
		errno=ENOENT;
		return (-1);
	}

	/* Exit if any of the following :
	 *   - user's password field in the passwd entry is empty
	 *   - supplied current password doesnt match stored password
	 */
	if (vpw->pw_passwd == 0 || authcheckpassword(pass, vpw->pw_passwd)) {
		errno=EPERM;
		return (-1);
	}

	/* save the new password into the auth backend */
	if ( vpasswd(User, Domain, (char *)npass, 0) != 0 ) {
		/* password set failed */
		return (-1);
	};

	return (0);
}

struct authstaticinfo authvchkpw_info={
	"authvchkpw",
	auth_vchkpw,
	auth_vchkpw_pre,
	authvchkpwclose,
	auth_vchkpw_changepass,
	authvchkpwclose,
	NULL};


struct authstaticinfo *courier_authvchkpw_init()
{
	return &authvchkpw_info;
}