/* print a CFNumber as CSSM_RETURN string */ void printCssmErr( CFNumberRef cfNum) { SInt32 s; if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &s)) { printf("***CFNumber overflow***"); return; } printf("%s", cssmErrorString((CSSM_RETURN)s)); }
const char * sec_errstr(int err) { const char *errString; if (IS_SEC_ERROR(err)) errString = SECErrorString(err); else errString = cssmErrorString(err); return errString; }
int display_error_code(int argc, char *const *argv) { CSSM_RETURN error; int ix = 0; for (ix = 0; ix < argc; ix++) { if (strcmp("error", argv[ix])==0) continue; // set base to 0 to have it interpret radix automatically error = strtoul(argv[ix], NULL, 0); printf("Error: 0x%08X %d %s\n", error, error, cssmErrorString(error)); } return 1; }
const char * sec_errstr(int err) { #if 1 static int bufnum = 0; static char buf[2][20]; bufnum = bufnum ? 0 : 1; sprintf(buf[bufnum], "0x%X", err); return buf[bufnum]; #else /* !1 */ if (err >= errSecErrnoBase && err <= errSecErrnoLimit) return strerror(err - 100000); #ifdef MAC_OS_X_VERSION_10_4 /* AvailabilityMacros.h would only define this if we are on a Tiger or later machine. */ extern const char *cssmErrorString(long); return cssmErrorString(err); #else /* !defined(MAC_OS_X_VERSION_10_4) */ extern const char *_ZN8Security15cssmErrorStringEl(long); return _ZN8Security15cssmErrorStringEl(err); #endif /* MAC_OS_X_VERSION_10_4 */ #endif /* !1 */ }
static int /* O - 0 if available */ /* 1 if not available */ /* -1 error */ cups_local_auth(http_t *http) /* I - HTTP connection to server */ { #if defined(WIN32) || defined(__EMX__) /* * Currently WIN32 and OS-2 do not support the CUPS server... */ return (1); #else int pid; /* Current process ID */ FILE *fp; /* Certificate file */ char trc[16], /* Try Root Certificate parameter */ filename[1024]; /* Certificate filename */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ # if defined(HAVE_AUTHORIZATION_H) OSStatus status; /* Status */ AuthorizationItem auth_right; /* Authorization right */ AuthorizationRights auth_rights; /* Authorization rights */ AuthorizationFlags auth_flags; /* Authorization flags */ AuthorizationExternalForm auth_extrn; /* Authorization ref external */ char auth_key[1024]; /* Buffer */ char buffer[1024]; /* Buffer */ # endif /* HAVE_AUTHORIZATION_H */ DEBUG_printf(("7cups_local_auth(http=%p) hostaddr=%s, hostname=\"%s\"", http, httpAddrString(http->hostaddr, filename, sizeof(filename)), http->hostname)); /* * See if we are accessing localhost... */ if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, "localhost") != 0) { DEBUG_puts("8cups_local_auth: Not a local connection!"); return (1); } # if defined(HAVE_AUTHORIZATION_H) /* * Delete any previous authorization reference... */ if (http->auth_ref) { AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults); http->auth_ref = NULL; } if (!getenv("GATEWAY_INTERFACE") && httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", auth_key, sizeof(auth_key))) { status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &http->auth_ref); if (status != errAuthorizationSuccess) { DEBUG_printf(("8cups_local_auth: AuthorizationCreate() returned %d (%s)", (int)status, cssmErrorString(status))); return (-1); } auth_right.name = auth_key; auth_right.valueLength = 0; auth_right.value = NULL; auth_right.flags = 0; auth_rights.count = 1; auth_rights.items = &auth_right; auth_flags = kAuthorizationFlagDefaults | kAuthorizationFlagPreAuthorize | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; status = AuthorizationCopyRights(http->auth_ref, &auth_rights, kAuthorizationEmptyEnvironment, auth_flags, NULL); if (status == errAuthorizationSuccess) status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn); if (status == errAuthorizationSuccess) { /* * Set the authorization string and return... */ httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn, sizeof(auth_extrn)); httpSetAuthString(http, "AuthRef", buffer); DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"", http->authstring)); return (0); } else if (status == errAuthorizationCanceled) return (-1); DEBUG_printf(("9cups_local_auth: AuthorizationCopyRights() returned %d (%s)", (int)status, cssmErrorString(status))); /* * Fall through to try certificates... */ } # endif /* HAVE_AUTHORIZATION_H */ # if defined(SO_PEERCRED) && defined(AF_LOCAL) /* * See if we can authenticate using the peer credentials provided over a * domain socket; if so, specify "PeerCred username" as the authentication * information... */ if ( # ifdef HAVE_GSSAPI _cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) && # endif /* HAVE_GSSAPI */ # ifdef HAVE_AUTHORIZATION_H !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", auth_key, sizeof(auth_key)) && # endif /* HAVE_AUTHORIZATION_H */ http->hostaddr->addr.sa_family == AF_LOCAL && !getenv("GATEWAY_INTERFACE")) /* Not via CGI programs... */ { /* * Verify that the current cupsUser() matches the current UID... */ struct passwd *pwd; /* Password information */ const char *username; /* Current username */ username = cupsUser(); if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid()) { httpSetAuthString(http, "PeerCred", username); DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"", http->authstring)); return (0); } } # endif /* SO_PEERCRED && AF_LOCAL */ /* * Try opening a certificate file for this PID. If that fails, * try the root certificate... */ pid = getpid(); snprintf(filename, sizeof(filename), "%s/certs/%d", cg->cups_statedir, pid); if ((fp = fopen(filename, "r")) == NULL && pid > 0) { /* * No certificate for this PID; see if we can get the root certificate... */ DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s", filename, strerror(errno))); # ifdef HAVE_GSSAPI if (!_cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9)) { /* * Kerberos required, don't try the root certificate... */ return (1); } # endif /* HAVE_GSSAPI */ # ifdef HAVE_AUTHORIZATION_H if (httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", auth_key, sizeof(auth_key))) { /* * Don't use the root certificate as a replacement for an authkey... */ return (1); } # endif /* HAVE_AUTHORIZATION_H */ if (!httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "trc", trc, sizeof(trc))) { /* * Scheduler doesn't want us to use the root certificate... */ return (1); } snprintf(filename, sizeof(filename), "%s/certs/0", cg->cups_statedir); fp = fopen(filename, "r"); } if (fp) { /* * Read the certificate from the file... */ char certificate[33], /* Certificate string */ *certptr; /* Pointer to certificate string */ certptr = fgets(certificate, sizeof(certificate), fp); fclose(fp); if (certptr) { /* * Set the authorization string and return... */ httpSetAuthString(http, "Local", certificate); DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"", http->authstring)); return (0); } } return (1); #endif /* WIN32 || __EMX__ */ }
int /* O - 1 on success, 0 on error */ cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ { OSStatus error = 0; /* Error code */ SecTrustRef peerTrust; /* Peer certificates */ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.", con->number); con->http->encryption = HTTP_ENCRYPTION_ALWAYS; con->http->tls_credentials = copy_cdsa_certificate(con); if (!con->http->tls_credentials) { /* * No keychain (yet), make a self-signed certificate... */ if (make_certificate(con)) con->http->tls_credentials = copy_cdsa_certificate(con); } if (!con->http->tls_credentials) { cupsdLogMessage(CUPSD_LOG_ERROR, "Could not find signing key in keychain \"%s\"", ServerCertificate); error = errSSLBadConfiguration; } if (!error) con->http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType); if (!error) error = SSLSetIOFuncs(con->http->tls, _httpReadCDSA, _httpWriteCDSA); if (!error) error = SSLSetConnection(con->http->tls, HTTP(con)); if (!error) error = SSLSetCertificate(con->http->tls, con->http->tls_credentials); if (!error) { /* * Perform SSL/TLS handshake */ while ((error = SSLHandshake(con->http->tls)) == errSSLWouldBlock) usleep(1000); } if (error) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to encrypt connection from %s - %s (%d)", con->http->hostname, cssmErrorString(error), (int)error); con->http->error = error; con->http->status = HTTP_ERROR; if (con->http->tls) { CFRelease(con->http->tls); con->http->tls = NULL; } if (con->http->tls_credentials) { CFRelease(con->http->tls_credentials); con->http->tls_credentials = NULL; } return (0); } cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", con->http->hostname); if (!SSLCopyPeerTrust(con->http->tls, &peerTrust) && peerTrust) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates.", (int)SecTrustGetCertificateCount(peerTrust)); CFRelease(peerTrust); } else cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates."); return (1); }
static CFArrayRef /* O - Array of certificates */ copy_cdsa_certificate( cupsd_client_t *con) /* I - Client connection */ { OSStatus err; /* Error info */ SecKeychainRef keychain = NULL;/* Keychain reference */ SecIdentitySearchRef search = NULL; /* Search reference */ SecIdentityRef identity = NULL;/* Identity */ CFArrayRef certificates = NULL; /* Certificate array */ SecPolicyRef policy = NULL; /* Policy ref */ CFStringRef servername = NULL; /* Server name */ CFMutableDictionaryRef query = NULL; /* Query qualifiers */ CFArrayRef list = NULL; /* Keychain list */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) char localname[1024];/* Local hostname */ # endif /* HAVE_DNSSD || HAVE_AVAHI */ cupsdLogMessage(CUPSD_LOG_DEBUG, "copy_cdsa_certificate: Looking for certs for \"%s\".", con->servername); if ((err = SecKeychainOpen(ServerCertificate, &keychain))) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)", ServerCertificate, cssmErrorString(err), (int)err); goto cleanup; } servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername, kCFStringEncodingUTF8); policy = SecPolicyCreateSSL(1, servername); if (servername) CFRelease(servername); if (!policy) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); goto cleanup; } if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks))) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary"); goto cleanup; } list = CFArrayCreate(kCFAllocatorDefault, (const void **)&keychain, 1, &kCFTypeArrayCallBacks); CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); CFDictionaryAddValue(query, kSecMatchPolicy, policy); CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne); CFDictionaryAddValue(query, kSecMatchSearchList, list); CFRelease(list); err = SecItemCopyMatching(query, (CFTypeRef *)&identity); # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (err && DNSSDHostName) { /* * Search for the connection server name failed; try the DNS-SD .local * hostname instead... */ snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); cupsdLogMessage(CUPSD_LOG_DEBUG, "copy_cdsa_certificate: Looking for certs for \"%s\".", localname); servername = CFStringCreateWithCString(kCFAllocatorDefault, localname, kCFStringEncodingUTF8); CFRelease(policy); policy = SecPolicyCreateSSL(1, servername); if (servername) CFRelease(servername); if (!policy) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); goto cleanup; } CFDictionarySetValue(query, kSecMatchPolicy, policy); err = SecItemCopyMatching(query, (CFTypeRef *)&identity); } # endif /* HAVE_DNSSD || HAVE_AVAHI */ if (err) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Cannot find signing key in keychain \"%s\": %s (%d)", ServerCertificate, cssmErrorString(err), (int)err); goto cleanup; } if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure."); goto cleanup; } if ((certificates = CFArrayCreate(NULL, (const void **)&identity, 1, &kCFTypeArrayCallBacks)) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array"); goto cleanup; } cleanup : if (keychain) CFRelease(keychain); if (search) CFRelease(search); if (identity) CFRelease(identity); if (policy) CFRelease(policy); if (query) CFRelease(query); return (certificates); }