]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
e07d4801 | 2 | * "$Id: usersys.c 8498 2009-04-13 17:03:15Z mike $" |
ef416fc2 | 3 | * |
4 | * User, system, and password routines for the Common UNIX Printing | |
5 | * System (CUPS). | |
6 | * | |
e07d4801 | 7 | * Copyright 2007-2009 by Apple Inc. |
ef416fc2 | 8 | * Copyright 1997-2006 by Easy Software Products. |
9 | * | |
10 | * These coded instructions, statements, and computer programs are the | |
bc44d920 | 11 | * property of Apple Inc. and are protected by Federal copyright |
12 | * law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
13 | * which should have been included with this file. If this file is | |
14 | * file is missing or damaged, see the license at "http://www.cups.org/". | |
ef416fc2 | 15 | * |
16 | * This file is subject to the Apple OS-Developed Software exception. | |
17 | * | |
18 | * Contents: | |
19 | * | |
b423cd4c | 20 | * cupsEncryption() - Get the default encryption settings. |
21 | * cupsGetPassword() - Get a password from the user. | |
e07d4801 MS |
22 | * cupsServer() - Return the hostname/address of the default |
23 | * server. | |
b423cd4c | 24 | * cupsSetEncryption() - Set the encryption preference. |
25 | * cupsSetPasswordCB() - Set the password callback for CUPS. | |
f11a948a | 26 | * cupsSetPasswordCB2() - Set the advanced password callback for CUPS. |
b423cd4c | 27 | * cupsSetServer() - Set the default server name. |
28 | * cupsSetUser() - Set the default user name. | |
e07d4801 | 29 | * cupsUser() - Return the current user's name. |
b423cd4c | 30 | * _cupsGetPassword() - Get a password from the user. |
e07d4801 MS |
31 | * _cupsSetDefaults() - Set the default server, port, and encryption. |
32 | * cups_read_client_conf() - Read a client.conf file. | |
ef416fc2 | 33 | */ |
34 | ||
35 | /* | |
36 | * Include necessary headers... | |
37 | */ | |
38 | ||
39 | #include "http-private.h" | |
40 | #include "globals.h" | |
41 | #include <stdlib.h> | |
e00b005a | 42 | #include <sys/stat.h> |
ef416fc2 | 43 | #ifdef WIN32 |
44 | # include <windows.h> | |
45 | #endif /* WIN32 */ | |
d09495fa | 46 | #include "debug.h" |
ef416fc2 | 47 | |
48 | ||
b423cd4c | 49 | /* |
50 | * Local functions... | |
51 | */ | |
52 | ||
e07d4801 MS |
53 | static void cups_read_client_conf(cups_file_t *fp, |
54 | _cups_globals_t *cg, | |
55 | const char *cups_encryption, | |
56 | const char *cups_server); | |
b423cd4c | 57 | |
58 | ||
ef416fc2 | 59 | /* |
60 | * 'cupsEncryption()' - Get the default encryption settings. | |
61 | * | |
62 | * The default encryption setting comes from the CUPS_ENCRYPTION | |
568fa3fa | 63 | * environment variable, then the ~/.cups/client.conf file, and finally the |
ef416fc2 | 64 | * /etc/cups/client.conf file. If not set, the default is |
5a738aea | 65 | * @code HTTP_ENCRYPT_IF_REQUESTED@. |
ef416fc2 | 66 | */ |
67 | ||
68 | http_encryption_t /* O - Encryption settings */ | |
69 | cupsEncryption(void) | |
70 | { | |
ef416fc2 | 71 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
72 | ||
73 | ||
ef416fc2 | 74 | if (cg->encryption == (http_encryption_t)-1) |
e07d4801 | 75 | _cupsSetDefaults(); |
ef416fc2 | 76 | |
77 | return (cg->encryption); | |
78 | } | |
79 | ||
80 | ||
81 | /* | |
82 | * 'cupsGetPassword()' - Get a password from the user. | |
83 | * | |
5a738aea | 84 | * Uses the current password callback function. Returns @code NULL@ if the |
ecdc0628 | 85 | * user does not provide a password. |
ef416fc2 | 86 | */ |
87 | ||
88 | const char * /* O - Password */ | |
89 | cupsGetPassword(const char *prompt) /* I - Prompt string */ | |
90 | { | |
f11a948a MS |
91 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
92 | ||
93 | ||
94 | return ((cg->password_cb)(prompt, NULL, NULL, NULL, cg->password_data)); | |
95 | } | |
96 | ||
97 | ||
98 | /* | |
99 | * 'cupsGetPassword2()' - Get a password from the user using the advanced | |
100 | * callback. | |
101 | * | |
102 | * Uses the current password callback function. Returns @code NULL@ if the | |
103 | * user does not provide a password. | |
104 | * | |
178cb736 | 105 | * @since CUPS 1.4/Mac OS X 10.6@ |
f11a948a MS |
106 | */ |
107 | ||
108 | const char * /* O - Password */ | |
109 | cupsGetPassword2(const char *prompt, /* I - Prompt string */ | |
110 | http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ | |
111 | const char *method, /* I - Request method ("GET", "POST", "PUT") */ | |
112 | const char *resource) /* I - Resource path */ | |
113 | { | |
114 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
115 | ||
116 | ||
117 | if (!http) | |
118 | http = _cupsConnect(); | |
119 | ||
120 | return ((cg->password_cb)(prompt, http, method, resource, cg->password_data)); | |
ef416fc2 | 121 | } |
122 | ||
123 | ||
ef416fc2 | 124 | /* |
125 | * 'cupsServer()' - Return the hostname/address of the default server. | |
126 | * | |
127 | * The returned value can be a fully-qualified hostname, a numeric | |
128 | * IPv4 or IPv6 address, or a domain socket pathname. | |
129 | */ | |
130 | ||
131 | const char * /* O - Server name */ | |
132 | cupsServer(void) | |
133 | { | |
ef416fc2 | 134 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
135 | ||
136 | ||
ef416fc2 | 137 | if (!cg->server[0]) |
e07d4801 | 138 | _cupsSetDefaults(); |
ef416fc2 | 139 | |
e07d4801 MS |
140 | return (cg->server); |
141 | } | |
ef416fc2 | 142 | |
d09495fa | 143 | |
e07d4801 MS |
144 | /* |
145 | * 'cupsSetEncryption()' - Set the encryption preference. | |
146 | */ | |
ef416fc2 | 147 | |
e07d4801 MS |
148 | void |
149 | cupsSetEncryption(http_encryption_t e) /* I - New encryption preference */ | |
150 | { | |
151 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
ef416fc2 | 152 | |
ef416fc2 | 153 | |
e07d4801 | 154 | cg->encryption = e; |
ef416fc2 | 155 | |
e07d4801 MS |
156 | if (cg->http) |
157 | httpEncryption(cg->http, e); | |
ef416fc2 | 158 | } |
159 | ||
160 | ||
161 | /* | |
162 | * 'cupsSetPasswordCB()' - Set the password callback for CUPS. | |
163 | * | |
5a738aea | 164 | * Pass @code NULL@ to restore the default (console) password callback. |
ef416fc2 | 165 | */ |
166 | ||
167 | void | |
168 | cupsSetPasswordCB(cups_password_cb_t cb)/* I - Callback function */ | |
169 | { | |
170 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
171 | ||
172 | ||
f11a948a MS |
173 | if (cb == (cups_password_cb_t)0) |
174 | cg->password_cb = (cups_password_cb2_t)_cupsGetPassword; | |
175 | else | |
176 | cg->password_cb = (cups_password_cb2_t)cb; | |
177 | ||
178 | cg->password_data = NULL; | |
179 | } | |
180 | ||
181 | ||
182 | /* | |
183 | * 'cupsSetPasswordCB2()' - Set the advanced password callback for CUPS. | |
184 | * | |
185 | * Pass @code NULL@ to restore the default (console) password callback. | |
186 | * | |
178cb736 | 187 | * @since CUPS 1.4/Mac OS X 10.6@ |
f11a948a MS |
188 | */ |
189 | ||
190 | void | |
191 | cupsSetPasswordCB2( | |
192 | cups_password_cb2_t cb, /* I - Callback function */ | |
193 | void *user_data) /* I - User data pointer */ | |
194 | { | |
195 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
196 | ||
197 | ||
198 | if (cb == (cups_password_cb2_t)0) | |
199 | cg->password_cb = (cups_password_cb2_t)_cupsGetPassword; | |
ef416fc2 | 200 | else |
201 | cg->password_cb = cb; | |
f11a948a MS |
202 | |
203 | cg->password_data = user_data; | |
ef416fc2 | 204 | } |
205 | ||
206 | ||
207 | /* | |
208 | * 'cupsSetServer()' - Set the default server name. | |
209 | * | |
210 | * The "server" string can be a fully-qualified hostname, a numeric | |
5a738aea | 211 | * IPv4 or IPv6 address, or a domain socket pathname. Pass @code NULL@ to |
ef416fc2 | 212 | * restore the default server name. |
213 | */ | |
214 | ||
215 | void | |
216 | cupsSetServer(const char *server) /* I - Server name */ | |
217 | { | |
218 | char *port; /* Pointer to port */ | |
219 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
220 | ||
221 | ||
222 | if (server) | |
223 | { | |
224 | strlcpy(cg->server, server, sizeof(cg->server)); | |
225 | ||
226 | if (cg->server[0] != '/' && (port = strrchr(cg->server, ':')) != NULL && | |
227 | !strchr(port, ']') && isdigit(port[1] & 255)) | |
228 | { | |
229 | *port++ = '\0'; | |
230 | ||
e07d4801 | 231 | cg->ipp_port = atoi(port); |
ef416fc2 | 232 | } |
233 | ||
234 | if (cg->server[0] == '/') | |
235 | strcpy(cg->servername, "localhost"); | |
236 | else | |
237 | strlcpy(cg->servername, cg->server, sizeof(cg->servername)); | |
238 | } | |
239 | else | |
240 | { | |
241 | cg->server[0] = '\0'; | |
242 | cg->servername[0] = '\0'; | |
243 | } | |
5a738aea MS |
244 | |
245 | if (cg->http) | |
246 | { | |
247 | httpClose(cg->http); | |
248 | cg->http = NULL; | |
249 | } | |
ef416fc2 | 250 | } |
251 | ||
252 | ||
253 | /* | |
254 | * 'cupsSetUser()' - Set the default user name. | |
255 | * | |
5a738aea | 256 | * Pass @code NULL@ to restore the default user name. |
ef416fc2 | 257 | */ |
258 | ||
259 | void | |
260 | cupsSetUser(const char *user) /* I - User name */ | |
261 | { | |
262 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
263 | ||
264 | ||
265 | if (user) | |
266 | strlcpy(cg->user, user, sizeof(cg->user)); | |
267 | else | |
268 | cg->user[0] = '\0'; | |
269 | } | |
270 | ||
271 | ||
272 | #if defined(WIN32) | |
273 | /* | |
274 | * WIN32 username and password stuff. | |
275 | */ | |
276 | ||
277 | /* | |
278 | * 'cupsUser()' - Return the current user's name. | |
279 | */ | |
280 | ||
281 | const char * /* O - User name */ | |
282 | cupsUser(void) | |
283 | { | |
284 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
285 | ||
286 | ||
287 | if (!cg->user[0]) | |
288 | { | |
289 | DWORD size; /* Size of string */ | |
290 | ||
291 | ||
292 | size = sizeof(cg->user); | |
293 | if (!GetUserName(cg->user, &size)) | |
294 | { | |
295 | /* | |
296 | * Use the default username... | |
297 | */ | |
298 | ||
299 | strcpy(cg->user, "unknown"); | |
300 | } | |
301 | } | |
302 | ||
303 | return (cg->user); | |
304 | } | |
305 | ||
306 | ||
307 | /* | |
308 | * '_cupsGetPassword()' - Get a password from the user. | |
309 | */ | |
310 | ||
311 | const char * /* O - Password */ | |
312 | _cupsGetPassword(const char *prompt) /* I - Prompt string */ | |
313 | { | |
314 | return (NULL); | |
315 | } | |
316 | #else | |
317 | /* | |
318 | * UNIX username and password stuff... | |
319 | */ | |
320 | ||
321 | # include <pwd.h> | |
322 | ||
323 | /* | |
324 | * 'cupsUser()' - Return the current user's name. | |
325 | */ | |
326 | ||
327 | const char * /* O - User name */ | |
328 | cupsUser(void) | |
329 | { | |
330 | struct passwd *pwd; /* User/password entry */ | |
331 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
332 | ||
333 | ||
334 | if (!cg->user[0]) | |
335 | { | |
336 | /* | |
337 | * Rewind the password file... | |
338 | */ | |
339 | ||
340 | setpwent(); | |
341 | ||
342 | /* | |
343 | * Lookup the password entry for the current user. | |
344 | */ | |
345 | ||
346 | if ((pwd = getpwuid(getuid())) == NULL) | |
347 | strcpy(cg->user, "unknown"); /* Unknown user! */ | |
348 | else | |
349 | { | |
350 | /* | |
351 | * Copy the username... | |
352 | */ | |
353 | ||
354 | setpwent(); | |
355 | ||
356 | strlcpy(cg->user, pwd->pw_name, sizeof(cg->user)); | |
357 | } | |
358 | ||
359 | /* | |
360 | * Rewind the password file again... | |
361 | */ | |
362 | ||
363 | setpwent(); | |
364 | } | |
365 | ||
366 | return (cg->user); | |
367 | } | |
368 | ||
369 | ||
370 | /* | |
371 | * '_cupsGetPassword()' - Get a password from the user. | |
372 | */ | |
373 | ||
374 | const char * /* O - Password */ | |
375 | _cupsGetPassword(const char *prompt) /* I - Prompt string */ | |
376 | { | |
377 | return (getpass(prompt)); | |
378 | } | |
379 | #endif /* WIN32 */ | |
380 | ||
381 | ||
382 | /* | |
e07d4801 | 383 | * '_cupsSetDefaults()' - Set the default server, port, and encryption. |
b423cd4c | 384 | */ |
385 | ||
e07d4801 MS |
386 | void |
387 | _cupsSetDefaults(void) | |
b423cd4c | 388 | { |
389 | cups_file_t *fp; /* File */ | |
e07d4801 MS |
390 | const char *home, /* Home directory of user */ |
391 | *cups_encryption, /* CUPS_ENCRYPTION env var */ | |
392 | *cups_server; /* CUPS_SERVER env var */ | |
b423cd4c | 393 | char filename[1024]; /* Filename */ |
394 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ | |
395 | ||
396 | ||
e07d4801 MS |
397 | DEBUG_puts("_cupsSetDefaults()"); |
398 | ||
399 | /* | |
400 | * First collect environment variables... | |
401 | */ | |
402 | ||
403 | cups_encryption = getenv("CUPS_ENCRYPTION"); | |
404 | cups_server = getenv("CUPS_SERVER"); | |
405 | ||
406 | /* | |
407 | * Then, if needed, the .cups/client.conf or .cupsrc file in the home | |
408 | * directory... | |
409 | */ | |
410 | ||
411 | if ((cg->encryption == (http_encryption_t)-1 || !cg->server[0] || | |
412 | !cg->ipp_port) && (home = getenv("HOME")) != NULL) | |
b423cd4c | 413 | { |
414 | /* | |
415 | * Look for ~/.cups/client.conf or ~/.cupsrc... | |
416 | */ | |
417 | ||
418 | snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home); | |
e07d4801 | 419 | if ((fp = cupsFileOpen(filename, "r")) == NULL) |
d09495fa | 420 | { |
e07d4801 MS |
421 | snprintf(filename, sizeof(filename), "%s/.cupsrc", home); |
422 | fp = cupsFileOpen(filename, "r"); | |
d09495fa | 423 | } |
b423cd4c | 424 | |
e07d4801 MS |
425 | if (fp) |
426 | { | |
427 | cups_read_client_conf(fp, cg, cups_encryption, cups_server); | |
428 | cupsFileClose(fp); | |
429 | } | |
430 | } | |
431 | ||
432 | if (cg->encryption == (http_encryption_t)-1 || !cg->server[0] || | |
433 | !cg->ipp_port) | |
434 | { | |
435 | /* | |
436 | * Look for CUPS_SERVERROOT/client.conf... | |
437 | */ | |
438 | ||
439 | snprintf(filename, sizeof(filename), "%s/client.conf", cg->cups_serverroot); | |
b423cd4c | 440 | if ((fp = cupsFileOpen(filename, "r")) != NULL) |
d09495fa | 441 | { |
e07d4801 MS |
442 | cups_read_client_conf(fp, cg, cups_encryption, cups_server); |
443 | cupsFileClose(fp); | |
444 | } | |
445 | } | |
446 | ||
447 | /* | |
448 | * If we still have things that aren't set, use the compiled in defaults... | |
449 | */ | |
450 | ||
451 | if (cg->encryption == (http_encryption_t)-1) | |
452 | cg->encryption = HTTP_ENCRYPT_IF_REQUESTED; | |
453 | ||
454 | if (!cg->server[0]) | |
455 | { | |
456 | if (!cups_server) | |
457 | { | |
458 | #ifdef CUPS_DEFAULT_DOMAINSOCKET | |
459 | /* | |
460 | * If we are compiled with domain socket support, only use the | |
461 | * domain socket if it exists and has the right permissions... | |
462 | */ | |
463 | ||
464 | struct stat sockinfo; /* Domain socket information */ | |
465 | ||
466 | if (!stat(CUPS_DEFAULT_DOMAINSOCKET, &sockinfo) && | |
467 | (sockinfo.st_mode & S_IRWXO) == S_IRWXO) | |
468 | cups_server = CUPS_DEFAULT_DOMAINSOCKET; | |
469 | else | |
470 | #endif /* CUPS_DEFAULT_DOMAINSOCKET */ | |
471 | cups_server = "localhost"; | |
472 | } | |
473 | ||
474 | cupsSetServer(cups_server); | |
475 | } | |
476 | ||
477 | if (!cg->ipp_port) | |
478 | { | |
479 | const char *ipp_port; /* IPP_PORT environment variable */ | |
480 | struct servent *service; /* Port number info */ | |
481 | ||
482 | ||
483 | if ((ipp_port = getenv("IPP_PORT")) != NULL) | |
484 | { | |
485 | if ((cg->ipp_port = atoi(ipp_port)) <= 0) | |
486 | cg->ipp_port = CUPS_DEFAULT_IPP_PORT; | |
d09495fa | 487 | } |
e07d4801 MS |
488 | else if ((service = getservbyname("ipp", NULL)) == NULL || |
489 | service->s_port <= 0) | |
490 | cg->ipp_port = CUPS_DEFAULT_IPP_PORT; | |
491 | else | |
492 | cg->ipp_port = ntohs(service->s_port); | |
493 | } | |
494 | } | |
495 | ||
496 | ||
497 | /* | |
498 | * 'cups_read_client_conf()' - Read a client.conf file. | |
499 | */ | |
500 | ||
501 | static void | |
502 | cups_read_client_conf( | |
503 | cups_file_t *fp, /* I - File to read */ | |
504 | _cups_globals_t *cg, /* I - Global data */ | |
505 | const char *cups_encryption, /* I - CUPS_ENCRYPTION env var */ | |
506 | const char *cups_server) /* I - CUPS_SERVER env var */ | |
507 | { | |
508 | int linenum; /* Current line number */ | |
509 | char line[1024], /* Line from file */ | |
510 | *value, /* Pointer into line */ | |
511 | encryption[1024], /* Encryption value */ | |
512 | server_name[1024]; /* ServerName value */ | |
513 | ||
514 | ||
515 | /* | |
516 | * Read from the file... | |
517 | */ | |
518 | ||
519 | linenum = 0; | |
520 | while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) | |
521 | { | |
522 | if (!cups_encryption && cg->encryption == (http_encryption_t)-1 && | |
523 | !strcasecmp(line, "Encryption") && value) | |
524 | { | |
525 | strlcpy(encryption, value, sizeof(encryption)); | |
526 | cups_encryption = encryption; | |
527 | } | |
528 | else if (!cups_server && (!cg->server[0] || !cg->ipp_port) && | |
529 | !strcasecmp(line, "ServerName") && value) | |
530 | { | |
531 | strlcpy(server_name, value, sizeof(server_name)); | |
532 | cups_server = server_name; | |
533 | } | |
534 | } | |
535 | ||
536 | /* | |
537 | * Set values... | |
538 | */ | |
539 | ||
540 | if (cg->encryption == (http_encryption_t)-1 && cups_encryption) | |
541 | { | |
542 | if (!strcasecmp(cups_encryption, "never")) | |
543 | cg->encryption = HTTP_ENCRYPT_NEVER; | |
544 | else if (!strcasecmp(cups_encryption, "always")) | |
545 | cg->encryption = HTTP_ENCRYPT_ALWAYS; | |
546 | else if (!strcasecmp(cups_encryption, "required")) | |
547 | cg->encryption = HTTP_ENCRYPT_REQUIRED; | |
548 | else | |
549 | cg->encryption = HTTP_ENCRYPT_IF_REQUESTED; | |
b423cd4c | 550 | } |
551 | ||
e07d4801 MS |
552 | if ((!cg->server[0] || !cg->ipp_port) && cups_server) |
553 | { | |
554 | if (!cg->server[0]) | |
555 | { | |
556 | /* | |
557 | * Copy server name... | |
558 | */ | |
559 | ||
560 | strlcpy(cg->server, cups_server, sizeof(cg->server)); | |
561 | ||
562 | if (cg->server[0] != '/' && (value = strrchr(cg->server, ':')) != NULL && | |
563 | !strchr(value, ']') && isdigit(value[1] & 255)) | |
564 | *value++ = '\0'; | |
565 | else | |
566 | value = NULL; | |
567 | ||
568 | if (cg->server[0] == '/') | |
569 | strcpy(cg->servername, "localhost"); | |
570 | else | |
571 | strlcpy(cg->servername, cg->server, sizeof(cg->servername)); | |
572 | } | |
573 | else if (cups_server[0] != '/' && | |
574 | (value = strrchr(cups_server, ':')) != NULL && | |
575 | !strchr(value, ']') && isdigit(value[1] & 255)) | |
576 | value ++; | |
577 | else | |
578 | value = NULL; | |
579 | ||
580 | if (!cg->ipp_port && value) | |
581 | cg->ipp_port = atoi(value); | |
582 | } | |
b423cd4c | 583 | } |
584 | ||
585 | ||
586 | /* | |
e07d4801 | 587 | * End of "$Id: usersys.c 8498 2009-04-13 17:03:15Z mike $". |
ef416fc2 | 588 | */ |