1 /* $Id: libauth.c 7500 2006-03-20 01:52:44Z eagle $
3 ** Common code for authenticators and resolvers.
5 ** Collects common code to read information from nnrpd that should be done
6 ** the same for all authenticators, and common code to get information about
7 ** the incoming connection.
15 #include "inn/messages.h"
17 #define NAMESTR "ClientAuthname: "
18 #define PASSSTR "ClientPassword: "
20 #define CLIHOST "ClientHost: "
21 #define CLIIP "ClientIP: "
22 #define CLIPORT "ClientPort: "
23 #define LOCIP "LocalIP: "
24 #define LOCPORT "LocalPort: "
30 /* Main loop. If res != NULL, expects to get resolver info from nnrpd, and
31 writes it into the struct. If auth != NULL, expects to get authentication
32 info from nnrpd, and writes it into the struct. */
35 get_connection_info(FILE *stream, struct res_info *res, struct auth_info *auth)
39 char *cip = NULL, *sip = NULL, *cport = NULL, *sport = NULL;
41 struct addrinfo *r, hints;
43 struct sockaddr_in *loc_sin, *cli_sin;
46 /* Zero fields first (anything remaining NULL after is missing data) */
48 res->clienthostname = NULL;
53 auth->username = NULL;
54 auth->password = NULL;
57 /* Read input from nnrpd a line at a time, stripping \r\n. */
58 while (fgets(buff, sizeof(buff), stream) != NULL) {
59 length = strlen(buff);
60 if (length == 0 || buff[length - 1] != '\n')
62 buff[length - 1] = '\0';
63 if (length > 1 && buff[length - 2] == '\r')
64 buff[length - 2] = '\0';
67 if (strncmp(buff, ".", 2) == 0)
69 else if (auth != NULL && strncmp(buff, NAMESTR, strlen(NAMESTR)) == 0)
70 auth->username = xstrdup(buff + strlen(NAMESTR));
71 else if (auth != NULL && strncmp(buff, PASSSTR, strlen(PASSSTR)) == 0)
72 auth->password = xstrdup(buff + strlen(PASSSTR));
73 else if (res != NULL && strncmp(buff, CLIHOST, strlen(CLIHOST)) == 0)
74 res->clienthostname = xstrdup(buff + strlen(CLIHOST));
75 else if (res != NULL && strncmp(buff, CLIIP, strlen(CLIIP)) == 0)
76 cip = xstrdup(buff + strlen(CLIIP));
77 else if (res != NULL && strncmp(buff, CLIPORT, strlen(CLIPORT)) == 0)
78 cport = xstrdup(buff + strlen(CLIPORT));
79 else if (res != NULL && strncmp(buff, LOCIP, strlen(LOCIP)) == 0)
80 sip = xstrdup(buff + strlen(LOCIP));
81 else if (res != NULL && strncmp(buff, LOCPORT, strlen(LOCPORT)) == 0)
82 sport = xstrdup(buff + strlen(LOCPORT));
84 /**** We just ignore excess fields for now ****/
86 /* warn("libauth: unexpected data from nnrpd: \"%s\"", buff); */
91 /* If some field is missing, free the rest and error out. */
92 if (auth != NULL && (auth->username == NULL || auth->password == NULL)) {
93 warn("libauth: requested authenticator data not sent by nnrpd");
96 if (res != NULL && (res->clienthostname == NULL || cip == NULL ||
97 cport == NULL || sip == NULL || sport == NULL)) {
98 warn("libauth: requested resolver data not sent by nnrpd");
102 /* Generate sockaddrs from IP and port strings */
105 /* sockaddr_in6 may be overkill for PF_INET case, but oh well */
106 res->client = xcalloc(1, sizeof(struct sockaddr_in6));
107 res->local = xcalloc(1, sizeof(struct sockaddr_in6));
109 memset( &hints, 0, sizeof( hints ) );
110 hints.ai_flags = AI_NUMERICHOST;
111 hints.ai_socktype = SOCK_STREAM;
113 hints.ai_family = strchr( cip, ':' ) != NULL ? PF_INET6 : PF_INET;
114 if( getaddrinfo( cip, cport, &hints, &r ) != 0)
116 if( r->ai_addrlen > sizeof(struct sockaddr_in6) )
118 memcpy( res->client, r->ai_addr, r->ai_addrlen );
121 hints.ai_family = strchr( sip, ':' ) != NULL ? PF_INET6 : PF_INET;
122 if( getaddrinfo( sip, sport, &hints, &r ) != 0)
124 if( r->ai_addrlen > sizeof(struct sockaddr_in6) )
126 memcpy( res->local, r->ai_addr, r->ai_addrlen );
129 res->client = xcalloc(1, sizeof(struct sockaddr_in));
130 res->local = xcalloc(1, sizeof(struct sockaddr_in));
132 cli_sin = (struct sockaddr_in *)(res->client);
133 loc_sin = (struct sockaddr_in *)(res->local);
134 cli_sin->sin_family = AF_INET;
135 if (!inet_aton(cip, &cli_sin->sin_addr))
137 cli_sin->sin_port = htons( atoi(cport) );
139 loc_sin->sin_family = AF_INET;
140 if (!inet_aton(sip, &loc_sin->sin_addr))
142 loc_sin->sin_port = htons( atoi(sport) );
144 # ifdef HAVE_SOCKADDR_LEN
145 cli_sin->sin_len = sizeof(struct sockaddr_in);
146 loc_sin->sin_len = sizeof(struct sockaddr_in);
159 if (auth != NULL && auth->username != NULL) free(auth->username);
160 if (auth != NULL && auth->password != NULL) free(auth->password);
161 if (res != NULL && res->clienthostname != NULL) free(res->clienthostname);
162 if (res != NULL && res->client != NULL) free(res->client);
163 if (res != NULL && res->local != NULL) free(res->local);
164 if (sip != NULL) free(sip);
165 if (sport != NULL) free(sport);
166 if (cip != NULL) free(cip);
167 if (cport != NULL) free(cport);
172 /* Wrappers to read information from nnrpd, returning an allocated struct on
176 get_res_info(FILE *stream) {
177 struct res_info *res = xmalloc(sizeof(struct res_info));
179 if(get_connection_info(stream, res, NULL))
188 get_auth_info(FILE *stream) {
189 struct auth_info *auth = xmalloc(sizeof(struct auth_info));
191 if(get_connection_info(stream, NULL, auth))
199 free_res_info(struct res_info *res) {
202 if(res->client != NULL) free(res->client);
203 if(res->local != NULL) free(res->local);
204 if(res->clienthostname != NULL) free(res->clienthostname);
209 free_auth_info(struct auth_info *auth) {
212 if(auth->username != NULL) free(auth->username);
213 if(auth->password != NULL) free(auth->password);