]>
Commit | Line | Data |
---|---|---|
0e550316 | 1 | /* |
c9d3f842 | 2 | * "$Id$" |
0e550316 | 3 | * |
4 | * Authentication functions for the Common UNIX Printing System (CUPS). | |
5 | * | |
c9d3f842 | 6 | * Copyright 1997-2005 by Easy Software Products. |
0e550316 | 7 | * |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
17 | * 44141 Airport View Drive, Suite 204 | |
c9d3f842 | 18 | * Hollywood, Maryland 20636 USA |
0e550316 | 19 | * |
c4dcf3cc | 20 | * Voice: (301) 373-9600 |
0e550316 | 21 | * EMail: cups-info@cups.org |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * This file is subject to the Apple OS-Developed Software exception. | |
25 | * | |
26 | * Contents: | |
27 | * | |
28 | * cupsDoAuthentication() - Authenticate a request... | |
29 | * cups_local_auth() - Get the local authorization certificate if | |
30 | * available/applicable... | |
31 | */ | |
32 | ||
33 | /* | |
34 | * Include necessary headers... | |
35 | */ | |
36 | ||
37 | #include "cups.h" | |
38 | #include "ipp.h" | |
39 | #include "language.h" | |
40 | #include "string.h" | |
41 | #include "debug.h" | |
42 | #include <stdlib.h> | |
43 | #include <ctype.h> | |
44 | #include <errno.h> | |
45 | #include <fcntl.h> | |
46 | #include <sys/stat.h> | |
47 | #if defined(WIN32) || defined(__EMX__) | |
48 | # include <io.h> | |
49 | #else | |
50 | # include <unistd.h> | |
51 | #endif /* WIN32 || __EMX__ */ | |
52 | ||
53 | ||
54 | /* | |
55 | * Local functions... | |
56 | */ | |
57 | ||
58 | static int cups_local_auth(http_t *http); | |
59 | ||
60 | ||
61 | /* | |
62 | * 'cupsDoAuthentication()' - Authenticate a request... | |
63 | */ | |
64 | ||
65 | int /* O - 0 on success, -1 on error */ | |
66 | cupsDoAuthentication(http_t *http, /* I - HTTP connection to server */ | |
67 | const char *method,/* I - Request method (GET, POST, PUT) */ | |
68 | const char *resource) | |
69 | /* I - Resource path */ | |
70 | { | |
71 | const char *password; /* Password string */ | |
72 | char prompt[1024], /* Prompt for user */ | |
73 | realm[HTTP_MAX_VALUE], /* realm="xyz" string */ | |
74 | nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */ | |
75 | encode[512]; /* Encoded username:password */ | |
76 | ||
77 | ||
4cdd993e | 78 | DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")\n", |
79 | http, method, resource)); | |
cda1bd04 | 80 | DEBUG_printf(("cupsDoAuthentication: digest_tries=%d, userpass=\"%s\"\n", |
81 | http->digest_tries, http->userpass)); | |
4cdd993e | 82 | |
0e550316 | 83 | /* |
84 | * Clear the current authentication string... | |
85 | */ | |
86 | ||
87 | http->authstring[0] = '\0'; | |
88 | ||
89 | /* | |
90 | * See if we can do local authentication... | |
91 | */ | |
92 | ||
93 | if (!cups_local_auth(http)) | |
4cdd993e | 94 | { |
95 | DEBUG_printf(("cupsDoAuthentication: authstring=\"%s\"\n", http->authstring)); | |
0e550316 | 96 | return (0); |
4cdd993e | 97 | } |
0e550316 | 98 | |
99 | /* | |
f1ea144d | 100 | * Nope, see if we should retry the current username:password... |
0e550316 | 101 | */ |
102 | ||
f1ea144d | 103 | if (http->digest_tries > 1 || !http->userpass[0]) |
0e550316 | 104 | { |
105 | /* | |
106 | * Nope - get a new password from the user... | |
107 | */ | |
108 | ||
109 | snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(), | |
110 | http->hostname); | |
111 | ||
f1ea144d | 112 | http->digest_tries = strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], |
352ab579 | 113 | "Digest", 5) != 0; |
0e550316 | 114 | http->userpass[0] = '\0'; |
115 | ||
116 | if ((password = cupsGetPassword(prompt)) == NULL) | |
117 | return (-1); | |
118 | ||
119 | if (!password[0]) | |
120 | return (-1); | |
121 | ||
122 | snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(), | |
123 | password); | |
124 | } | |
f1ea144d | 125 | else if (http->status == HTTP_UNAUTHORIZED) |
0e550316 | 126 | http->digest_tries ++; |
127 | ||
128 | /* | |
129 | * Got a password; encode it for the server... | |
130 | */ | |
131 | ||
352ab579 | 132 | if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6)) |
0e550316 | 133 | { |
134 | /* | |
135 | * Basic authentication... | |
136 | */ | |
137 | ||
138 | httpEncode64(encode, http->userpass); | |
139 | snprintf(http->authstring, sizeof(http->authstring), "Basic %s", encode); | |
140 | } | |
141 | else | |
142 | { | |
143 | /* | |
144 | * Digest authentication... | |
145 | */ | |
146 | ||
147 | httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm); | |
148 | httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce); | |
149 | ||
150 | httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode); | |
0cb462af | 151 | httpMD5Final(nonce, method, resource, encode); |
0e550316 | 152 | snprintf(http->authstring, sizeof(http->authstring), |
153 | "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " | |
891091df | 154 | "uri=\"%s\", response=\"%s\"", cupsUser(), realm, nonce, |
155 | resource, encode); | |
0e550316 | 156 | } |
157 | ||
4cdd993e | 158 | DEBUG_printf(("cupsDoAuthentication: authstring=\"%s\"\n", http->authstring)); |
159 | ||
0e550316 | 160 | return (0); |
161 | } | |
162 | ||
163 | ||
164 | /* | |
165 | * 'cups_local_auth()' - Get the local authorization certificate if | |
166 | * available/applicable... | |
167 | */ | |
168 | ||
169 | static int /* O - 0 if available, -1 if not */ | |
170 | cups_local_auth(http_t *http) /* I - HTTP connection to server */ | |
171 | { | |
172 | #if defined(WIN32) || defined(__EMX__) | |
173 | /* | |
174 | * Currently WIN32 and OS-2 do not support the CUPS server... | |
175 | */ | |
176 | ||
177 | return (-1); | |
178 | #else | |
179 | int pid; /* Current process ID */ | |
180 | FILE *fp; /* Certificate file */ | |
181 | char filename[1024], /* Certificate filename */ | |
182 | certificate[33]; /* Certificate string */ | |
d4102150 | 183 | const char *state; /* Server state directory */ |
0e550316 | 184 | |
185 | ||
186 | DEBUG_printf(("cups_local_auth(http=%p) hostaddr=%08x, hostname=\"%s\"\n", | |
187 | http, ntohl(http->hostaddr.sin_addr.s_addr), http->hostname)); | |
188 | ||
189 | /* | |
190 | * See if we are accessing localhost... | |
191 | */ | |
192 | ||
086c584d | 193 | if (!httpAddrLocalhost(http->hostaddr) && |
0e550316 | 194 | strcasecmp(http->hostname, "localhost") != 0) |
195 | { | |
196 | DEBUG_puts("cups_local_auth: Not a local connection!"); | |
197 | return (-1); | |
198 | } | |
199 | ||
200 | /* | |
201 | * Try opening a certificate file for this PID. If that fails, | |
202 | * try the root certificate... | |
203 | */ | |
204 | ||
d4102150 | 205 | if ((state = getenv("CUPS_STATEDIR")) == NULL) |
206 | state = CUPS_STATEDIR; | |
0e550316 | 207 | |
208 | pid = getpid(); | |
d4102150 | 209 | snprintf(filename, sizeof(filename), "%s/certs/%d", state, pid); |
0e550316 | 210 | if ((fp = fopen(filename, "r")) == NULL && pid > 0) |
211 | { | |
212 | DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n", | |
213 | filename, strerror(errno))); | |
214 | ||
d4102150 | 215 | snprintf(filename, sizeof(filename), "%s/certs/0", state); |
0e550316 | 216 | fp = fopen(filename, "r"); |
217 | } | |
218 | ||
219 | if (fp == NULL) | |
220 | { | |
221 | DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n", | |
222 | filename, strerror(errno))); | |
223 | return (-1); | |
224 | } | |
225 | ||
226 | /* | |
227 | * Read the certificate from the file... | |
228 | */ | |
229 | ||
230 | fgets(certificate, sizeof(certificate), fp); | |
231 | fclose(fp); | |
232 | ||
233 | /* | |
234 | * Set the authorization string and return... | |
235 | */ | |
236 | ||
237 | snprintf(http->authstring, sizeof(http->authstring), "Local %s", certificate); | |
238 | ||
239 | DEBUG_printf(("cups_local_auth: Returning authstring = \"%s\"\n", | |
0669cbc7 | 240 | http->authstring)); |
0e550316 | 241 | |
242 | return (0); | |
243 | #endif /* WIN32 || __EMX__ */ | |
244 | } | |
245 | ||
246 | ||
247 | /* | |
c9d3f842 | 248 | * End of "$Id$". |
0e550316 | 249 | */ |