DEBUG_printf("3avahi_resolve_cb(resolver=%p, if_index=%d, protocol=%d, event=%s, name=\"%s\", type=\"%s\", domain=\"%s\", host=\"%s\", address=%p, port=%u, txtrec=%p, flags=%u, resolve=%p)", (void *)resolver, if_index, protocol, avahi_events[event], name, type, domain, host, (void *)address, (unsigned)port, (void *)txtrec, (unsigned)flags, (void *)resolve);
- if (!resolver || event != AVAHI_RESOLVER_FOUND)
+ if (!resolver)
return;
- (void)resolver;
(void)protocol;
(void)flags;
// Map the addresses "127.0.0.1" (IPv4) and "::1" (IPv6) to "localhost" to work around a well-known Avahi registration bug for local-only services (Issue #970)
- if (address->proto == AVAHI_PROTO_INET && address->data.ipv4.address == htonl(0x7f000001))
+ if (address && address->proto == AVAHI_PROTO_INET && address->data.ipv4.address == htonl(0x7f000001))
{
DEBUG_puts("4avahi_resolve_cb: Mapping 127.0.0.1 to localhost.");
host = "localhost";
}
- else if (address->proto == AVAHI_PROTO_INET6 && address->data.ipv6.address[0] == 0 && address->data.ipv6.address[1] == 0 && address->data.ipv6.address[2] == 0 && address->data.ipv6.address[3] == 0 && address->data.ipv6.address[4] == 0 && address->data.ipv6.address[5] == 0 && address->data.ipv6.address[6] == 0 && address->data.ipv6.address[7] == 0 && address->data.ipv6.address[8] == 0 && address->data.ipv6.address[9] == 0 && address->data.ipv6.address[10] == 0 && address->data.ipv6.address[11] == 0 && address->data.ipv6.address[12] == 0 && address->data.ipv6.address[13] == 0 && address->data.ipv6.address[14] == 0 && address->data.ipv6.address[15] == 1)
+ else if (address && address->proto == AVAHI_PROTO_INET6 && address->data.ipv6.address[0] == 0 && address->data.ipv6.address[1] == 0 && address->data.ipv6.address[2] == 0 && address->data.ipv6.address[3] == 0 && address->data.ipv6.address[4] == 0 && address->data.ipv6.address[5] == 0 && address->data.ipv6.address[6] == 0 && address->data.ipv6.address[7] == 0 && address->data.ipv6.address[8] == 0 && address->data.ipv6.address[9] == 0 && address->data.ipv6.address[10] == 0 && address->data.ipv6.address[11] == 0 && address->data.ipv6.address[12] == 0 && address->data.ipv6.address[13] == 0 && address->data.ipv6.address[14] == 0 && address->data.ipv6.address[15] == 1)
{
DEBUG_puts("4avahi_resolve_cb: Mapping ::1 to localhost.");
host = "localhost";
{
DEBUG_puts("2httpPeek: Unable to copy decompressor stream.");
http->error = ENOMEM;
+ inflateEnd(&stream);
return (-1);
}
*cnptr; // Pointer into common name
bool have_creds = false; // Have credentials?
+ cupsMutexLock(&tls_mutex);
+
if (!tls_common_name)
{
+ cupsMutexUnlock(&tls_mutex);
+
if (http->fields[HTTP_FIELD_HOST])
{
// Use hostname for TLS upgrade...
if (hostname[0])
cn = hostname;
- }
- cupsMutexLock(&tls_mutex);
+ cupsMutexLock(&tls_mutex);
+ }
if (!cn)
cn = tls_common_name;
context = SSL_CTX_new(TLS_server_method());
// Find the TLS certificate...
+ cupsMutexLock(&tls_mutex);
+
if (!tls_common_name)
{
+ cupsMutexUnlock(&tls_mutex);
+
if (http->fields[HTTP_FIELD_HOST])
{
// Use hostname for TLS upgrade...
if (hostname[0])
cn = hostname;
- }
- cupsMutexLock(&tls_mutex);
+ cupsMutexLock(&tls_mutex);
+ }
if (!cn)
cn = tls_common_name;
ipp_attribute_t *username; /* requesting-user-name attr */
int sub_id; /* Subscription ID */
int valid = 1; /* Valid request? */
- int minor; /* Minor version */
+ int major, /* IPP major version */
+ minor; /* IPP minor version */
- cupsdLogClient(con, CUPSD_LOG_DEBUG, "%s IPP/%d.%d request_id=%d", ippOpString(ippGetOperation(con->request)), ippGetVersion(con->request, &minor), minor, ippGetRequestId(con->request));
+ major = ippGetVersion(con->request, &minor);
+
+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "%s IPP/%d.%d request_id=%d", ippOpString(ippGetOperation(con->request)), major, minor, ippGetRequestId(con->request));
if (LogLevel >= CUPSD_LOG_DEBUG2)
{
*/
while ((dent = cupsDirRead(dir)) != NULL)
+ {
if (strlen(dent->filename) >= 6 && dent->filename[0] == 'c')
{
/*
cupsdDeleteJob(job, CUPSD_JOB_FORCE);
}
}
+ }
cupsDirClose(dir);
}
/*
* Generic HP PCL printer command for ippeveprinter/CUPS.
*
- * Copyright © 2020-2024 by OpenPrinting.
+ * Copyright © 2020-2025 by OpenPrinting.
* Copyright © 2019 by Apple Inc.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
break;
}
- line = malloc(header.cupsBytesPerLine);
+ if ((line = malloc(header.cupsBytesPerLine)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Unable to allocate %u bytes for line, aborting.\n", header.cupsBytesPerLine);
+ break;
+ }
pcl_start_page(&header, page);
for (y = 0; y < header.cupsHeight; y ++)
break;
}
- line = malloc(header.cupsBytesPerLine);
+ if ((line = malloc(header.cupsBytesPerLine)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Unable to allocate %u bytes for line, aborting.\n", header.cupsBytesPerLine);
+ break;
+ }
dsc_page(page);
buildPhases = (
);
dependencies = (
+ 27C3E96E2DB04B5800A6ABBF /* PBXTargetDependency */,
+ 27C3E9702DB04B5800A6ABBF /* PBXTargetDependency */,
273B1EC2226B3F2600428143 /* PBXTargetDependency */,
273B1EC4226B3F2600428143 /* PBXTargetDependency */,
271287061CC13F8F00E517C7 /* PBXTargetDependency */,
27B493ED2C8FC36E004C7A73 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 2758FE1C2C8FBD2B0078480C /* libiconv.tbd */; };
27B493EE2C8FC37B004C7A73 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2758FE182C8F9F5E0078480C /* CoreServices.framework */; };
27B493EF2C8FC389004C7A73 /* GSS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27865F092C8FC0A5003D5606 /* GSS.framework */; };
+ 27C3E9562DB04AC500A6ABBF /* libcups2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 72220EAE1333047D00FCA411 /* libcups2.dylib */; };
+ 27C3E9622DB04ACE00A6ABBF /* libcups2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 72220EAE1333047D00FCA411 /* libcups2.dylib */; };
+ 27C3E96B2DB04B2900A6ABBF /* cups-oauth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27C3E9682DB04AFB00A6ABBF /* cups-oauth.c */; };
+ 27C3E96C2DB04B3600A6ABBF /* cups-x509.c in Sources */ = {isa = PBXBuildFile; fileRef = 27C3E9692DB04AFB00A6ABBF /* cups-x509.c */; };
27F515462AAFBECF0045EE21 /* raster-testpage.h in Headers */ = {isa = PBXBuildFile; fileRef = 27F515432AAFBECF0045EE21 /* raster-testpage.h */; };
27F515472AAFBECF0045EE21 /* raster-testpage.h in Headers */ = {isa = PBXBuildFile; fileRef = 27F515432AAFBECF0045EE21 /* raster-testpage.h */; };
27F515482AAFBECF0045EE21 /* raster-testpage.h in Headers */ = {isa = PBXBuildFile; fileRef = 27F515432AAFBECF0045EE21 /* raster-testpage.h */; };
remoteGlobalIDString = 27A0347A1A8BDB1200650675;
remoteInfo = lpadmin;
};
+ 27C3E9522DB04AC500A6ABBF /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 72BF96371333042100B1EAD7 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72220EAD1333047D00FCA411;
+ remoteInfo = libcups;
+ };
+ 27C3E95E2DB04ACE00A6ABBF /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 72BF96371333042100B1EAD7 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72220EAD1333047D00FCA411;
+ remoteInfo = libcups;
+ };
+ 27C3E96D2DB04B5800A6ABBF /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 72BF96371333042100B1EAD7 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 27C3E95C2DB04ACE00A6ABBF;
+ remoteInfo = "cups-oauth";
+ };
+ 27C3E96F2DB04B5800A6ABBF /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 72BF96371333042100B1EAD7 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 27C3E9502DB04AC500A6ABBF;
+ remoteInfo = "cups-x509";
+ };
720DD6CE1358FD790064AA82 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 72BF96371333042100B1EAD7 /* Project object */;
);
runOnlyForDeploymentPostprocessing = 1;
};
+ 27C3E9572DB04AC500A6ABBF /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 27C3E9632DB04ACE00A6ABBF /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
720DD6C01358FD5F0064AA82 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
278C58E8136B64B000836530 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = "<absolute>"; };
279AE6F42395B80F004DD600 /* libpam.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libpam.tbd; path = usr/lib/libpam.tbd; sourceTree = SDKROOT; };
27A0347B1A8BDB1300650675 /* lpadmin */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lpadmin; sourceTree = BUILT_PRODUCTS_DIR; };
+ 27C3E95B2DB04AC500A6ABBF /* cups-x509 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "cups-x509"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 27C3E9672DB04ACE00A6ABBF /* cups-oauth */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "cups-oauth"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 27C3E9682DB04AFB00A6ABBF /* cups-oauth.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "cups-oauth.c"; sourceTree = "<group>"; };
+ 27C3E9692DB04AFB00A6ABBF /* cups-x509.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "cups-x509.c"; sourceTree = "<group>"; };
27C89C902613E7C300A58F43 /* cups-tls.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-tls.m4"; path = "../config-scripts/cups-tls.m4"; sourceTree = "<group>"; };
27D3037D134148CB00F022B1 /* libcups2.def */ = {isa = PBXFileReference; lastKnownFileType = text; name = libcups2.def; path = ../cups/libcups2.def; sourceTree = "<group>"; };
27F515432AAFBECF0045EE21 /* raster-testpage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "raster-testpage.h"; path = "../cups/raster-testpage.h"; sourceTree = "<group>"; };
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 27C3E9552DB04AC500A6ABBF /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 27C3E9562DB04AC500A6ABBF /* libcups2.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27C3E9612DB04ACE00A6ABBF /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 27C3E9622DB04ACE00A6ABBF /* libcups2.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
720DD6BF1358FD5F0064AA82 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
276683681337AA00000D33D0 /* cupsctl.c */,
274FF68713333B6E00317ECB /* cupsfilter.c */,
72F75A5B1336F988004BB496 /* cupstestppd.c */,
+ 27C3E9682DB04AFB00A6ABBF /* cups-oauth.c */,
+ 27C3E9692DB04AFB00A6ABBF /* cups-x509.c */,
273B1EBD226B3EE300428143 /* ippevecommon.h */,
273B1EBE226B3EE300428143 /* ippevepcl.c */,
726AD701135E8A90002C930D /* ippeveprinter.c */,
2758FDF62C8F9C240078480C /* testoauth */,
2758FE072C8F9C5B0078480C /* testform */,
275CEA422CC840EE008FBB27 /* testclock */,
+ 27C3E95B2DB04AC500A6ABBF /* cups-x509 */,
+ 27C3E9672DB04ACE00A6ABBF /* cups-oauth */,
);
name = Products;
sourceTree = "<group>";
productReference = 27A0347B1A8BDB1300650675 /* lpadmin */;
productType = "com.apple.product-type.tool";
};
+ 27C3E9502DB04AC500A6ABBF /* cups-x509 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 27C3E9582DB04AC500A6ABBF /* Build configuration list for PBXNativeTarget "cups-x509" */;
+ buildPhases = (
+ 27C3E9532DB04AC500A6ABBF /* Sources */,
+ 27C3E9552DB04AC500A6ABBF /* Frameworks */,
+ 27C3E9572DB04AC500A6ABBF /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 27C3E9512DB04AC500A6ABBF /* PBXTargetDependency */,
+ );
+ name = "cups-x509";
+ productName = cupsaddsmb;
+ productReference = 27C3E95B2DB04AC500A6ABBF /* cups-x509 */;
+ productType = "com.apple.product-type.tool";
+ };
+ 27C3E95C2DB04ACE00A6ABBF /* cups-oauth */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 27C3E9642DB04ACE00A6ABBF /* Build configuration list for PBXNativeTarget "cups-oauth" */;
+ buildPhases = (
+ 27C3E95F2DB04ACE00A6ABBF /* Sources */,
+ 27C3E9612DB04ACE00A6ABBF /* Frameworks */,
+ 27C3E9632DB04ACE00A6ABBF /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 27C3E95D2DB04ACE00A6ABBF /* PBXTargetDependency */,
+ );
+ name = "cups-oauth";
+ productName = cupsaddsmb;
+ productReference = 27C3E9672DB04ACE00A6ABBF /* cups-oauth */;
+ productType = "com.apple.product-type.tool";
+ };
720DD6C11358FD5F0064AA82 /* snmp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 720DD6CB1358FD600064AA82 /* Build configuration list for PBXNativeTarget "snmp" */;
274FF6281333333600317ECB /* cups-deviced */,
274FF63D1333358B00317ECB /* cups-exec */,
274FF64E133339C400317ECB /* cups-lpd */,
+ 27C3E95C2DB04ACE00A6ABBF /* cups-oauth */,
+ 27C3E9502DB04AC500A6ABBF /* cups-x509 */,
274FF67713333B2F00317ECB /* cupsfilter */,
72F75A511336F950004BB496 /* cupstestppd */,
724379461333FEA9009631B9 /* dnssd */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 27C3E9532DB04AC500A6ABBF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 27C3E96C2DB04B3600A6ABBF /* cups-x509.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27C3E95F2DB04ACE00A6ABBF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 27C3E96B2DB04B2900A6ABBF /* cups-oauth.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
720DD6BE1358FD5F0064AA82 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
target = 27A0347A1A8BDB1200650675 /* lpadmin */;
targetProxy = 27A034861A8BDC6900650675 /* PBXContainerItemProxy */;
};
+ 27C3E9512DB04AC500A6ABBF /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72220EAD1333047D00FCA411 /* libcups2 */;
+ targetProxy = 27C3E9522DB04AC500A6ABBF /* PBXContainerItemProxy */;
+ };
+ 27C3E95D2DB04ACE00A6ABBF /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72220EAD1333047D00FCA411 /* libcups2 */;
+ targetProxy = 27C3E95E2DB04ACE00A6ABBF /* PBXContainerItemProxy */;
+ };
+ 27C3E96E2DB04B5800A6ABBF /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 27C3E95C2DB04ACE00A6ABBF /* cups-oauth */;
+ targetProxy = 27C3E96D2DB04B5800A6ABBF /* PBXContainerItemProxy */;
+ };
+ 27C3E9702DB04B5800A6ABBF /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 27C3E9502DB04AC500A6ABBF /* cups-x509 */;
+ targetProxy = 27C3E96F2DB04B5800A6ABBF /* PBXContainerItemProxy */;
+ };
720DD6CF1358FD790064AA82 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 72220EAD1333047D00FCA411 /* libcups2 */;
};
name = Release;
};
+ 27C3E9592DB04AC500A6ABBF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEAD_CODE_STRIPPING = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ INSTALL_PATH = /usr/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 27C3E95A2DB04AC500A6ABBF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEAD_CODE_STRIPPING = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ INSTALL_PATH = /usr/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 27C3E9652DB04ACE00A6ABBF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEAD_CODE_STRIPPING = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ INSTALL_PATH = /usr/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 27C3E9662DB04ACE00A6ABBF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEAD_CODE_STRIPPING = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ INSTALL_PATH = /usr/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
720DD6C91358FD5F0064AA82 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 27C3E9582DB04AC500A6ABBF /* Build configuration list for PBXNativeTarget "cups-x509" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 27C3E9592DB04AC500A6ABBF /* Debug */,
+ 27C3E95A2DB04AC500A6ABBF /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 27C3E9642DB04ACE00A6ABBF /* Build configuration list for PBXNativeTarget "cups-oauth" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 27C3E9652DB04ACE00A6ABBF /* Debug */,
+ 27C3E9662DB04ACE00A6ABBF /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
720DD6CB1358FD600064AA82 /* Build configuration list for PBXNativeTarget "snmp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
--- /dev/null
+//
+// OAuth utility for CUPS.
+//
+// Copyright © 2024-2025 by OpenPrinting.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more
+// information.
+//
+// Usage: cups-oauth [OPTIONS] [COMMAND [ARGUMENT(S)]]
+//
+// Commands:
+//
+// authorize [RESOURCE]
+// clear [RESOURCE]
+// get-access-token [RESOURCE]
+// get-client-id
+// get-metadata [NAME]
+// get-refresh-token [RESOURCE]
+// get-user-id [RESOURCE] [NAME]
+// set-access-token [RESOURCE] TOKEN
+// set-client-data CLIENT-ID CLIENT-SECRET
+//
+// Options:
+//
+// --help
+// --version
+// -a OAUTH-URI
+// -s SCOPE(S)
+//
+
+#include <cups/cups-private.h>
+#include <cups/oauth.h>
+
+
+//
+// Macro for localized text...
+//
+
+# define _(x) x
+
+
+//
+// Local functions...
+//
+
+static int do_authorize(const char *oauth_uri, const char *scopes, const char *resource_uri);
+static int do_clear(const char *oauth_uri, const char *resource_uri);
+static int do_get_access_token(const char *oauth_uri, const char *resource_uri);
+static int do_get_client_id(const char *oauth_uri);
+static int do_get_metadata(const char *oauth_uri, const char *name);
+static int do_get_user_id(const char *oauth_uri, const char *resource_uri, const char *name);
+static int do_set_access_token(const char *oauth_uri, const char *resource_uri, const char *token);
+static int do_set_client_data(const char *oauth_uri, const char *client_id, const char *client_secret);
+static int usage(FILE *out);
+
+
+//
+// 'main()' - Main entry.
+//
+
+int // O - Exit status
+main(int argc, // I - Number of command-line arguments
+ char *argv[]) // I - Command-line arguments
+{
+ int i; // Looping var
+ const char *opt, // Current option
+ *oauth_uri = getenv("CUPS_OAUTH_URI"),
+ // OAuth authorization server URI
+ *scopes = getenv("CUPS_OAUTH_SCOPES");
+ // Scopes
+
+
+ // Parse the command-line...
+ for (i = 1; i < argc; i ++)
+ {
+ if (!strcmp(argv[i], "--help"))
+ {
+ return (usage(stdout));
+ }
+ else if (!strcmp(argv[i], "--version"))
+ {
+ puts(CUPS_SVERSION);
+ exit(0);
+ }
+ else if (!strncmp(argv[i], "--", 2))
+ {
+ _cupsLangPrintf(stderr, _("%s: Unknown option '%s'."), "cups-oauth", argv[i]);
+ return (usage(stderr));
+ }
+ else if (argv[i][0] == '-' && argv[i][1] != '-')
+ {
+ for (opt = argv[i] + 1; *opt; opt ++)
+ {
+ switch (*opt)
+ {
+ case 'a' : // -a AUTH-URI
+ i ++;
+ if (i >= argc)
+ {
+ _cupsLangPuts(stderr, _("cups-oauth: Missing Authorization Server URI after '-a'."));
+ return (usage(stderr));
+ }
+
+ oauth_uri = argv[i];
+ break;
+
+ case 's' : // -s SCOPE(S)
+ i ++;
+ if (i >= argc)
+ {
+ _cupsLangPuts(stderr, _("cups-oauth: Missing scope(s) after '-s'."));
+ return (usage(stderr));
+ }
+
+ scopes = argv[i];
+ break;
+
+ default :
+ _cupsLangPrintf(stderr, _("%s: Unknown option '-%c'."), "cups-oauth", *opt);
+ return (usage(stderr));
+ }
+ }
+ }
+ else if (!oauth_uri)
+ {
+ _cupsLangPuts(stderr, _("cups-oauth: No authorization server specified."));
+ return (usage(stderr));
+ }
+ else if (!strcmp(argv[i], "authorize"))
+ {
+ // authorize [RESOURCE]
+ i ++;
+ return (do_authorize(oauth_uri, scopes, argv[i]));
+ }
+ else if (!strcmp(argv[i], "clear"))
+ {
+ // clear [RESOURCE]
+ i ++;
+ return (do_clear(oauth_uri, argv[i]));
+ }
+ else if (!strcmp(argv[i], "get-access-token"))
+ {
+ // get-access-token [RESOURCE]
+ i ++;
+ return (do_get_access_token(oauth_uri, argv[i]));
+ }
+ else if (!strcmp(argv[i], "get-client-id"))
+ {
+ // get-client-id
+ i ++;
+ return (do_get_client_id(oauth_uri));
+ }
+ else if (!strcmp(argv[i], "get-metadata"))
+ {
+ // get-metadata [NAME]
+ i ++;
+ return (do_get_metadata(oauth_uri, argv[i]));
+ }
+ else if (!strcmp(argv[i], "get-user-id"))
+ {
+ // get-user-id [RESOURCE] [NAME]
+ i ++;
+ if (i < argc)
+ {
+ if (!strncmp(argv[i], "ipp://", 6) || !strncmp(argv[i], "ipps://", 7) || !strncmp(argv[i], "http://", 7) || !strncmp(argv[i], "https://", 8))
+ return (do_get_user_id(oauth_uri, argv[i], argv[i + 1]));
+ else
+ return (do_get_user_id(oauth_uri, /*resource_uri*/NULL, argv[i]));
+ }
+ else
+ {
+ return (do_get_user_id(oauth_uri, /*resource_uri*/NULL, /*name*/NULL));
+ }
+ }
+ else if (!strcmp(argv[i], "set-access-token"))
+ {
+ // set-access-token [RESOURCE] TOKEN
+ i ++;
+ if (i >= argc)
+ {
+ _cupsLangPuts(stderr, _("cups-oauth: Missing resource URI and/or access token."));
+ return (usage(stderr));
+ }
+
+ return (do_set_access_token(oauth_uri, argv[i], argv[i + 1]));
+ }
+ else if (!strcmp(argv[i], "set-client-data"))
+ {
+ // set-client-data CLIENT-ID CLIENT-DATA
+ i ++;
+ if ((i + 1) >= argc)
+ {
+ _cupsLangPuts(stderr, _("cups-oauth: Missing client_id and/or client_secret."));
+ return (usage(stderr));
+ }
+
+ return (do_set_client_data(oauth_uri, argv[i], argv[i + 1]));
+ }
+ else
+ {
+ _cupsLangPrintf(stderr, _("cups-oauth: Unknown command '%s'."), argv[i]);
+ return (usage(stderr));
+ }
+ }
+
+ // If we get this far, show usage...
+ return (usage(argc == 1 ? stdout : stderr));
+}
+
+
+//
+// 'do_authorize()' - Authorize access.
+//
+
+static int // O - Exit status
+do_authorize(const char *oauth_uri, // I - Authorization Server URI
+ const char *scopes, // I - Scope(s)
+ const char *resource_uri) // I - Resource URI
+{
+ int status = 1; // Exit status
+ cups_json_t *metadata; // Server metadata
+ char *auth_code = NULL, // Authorization code
+ *access_token = NULL; // Access token
+ time_t access_expires; // Expiration date
+
+
+ // Get the server metadata...
+ if ((metadata = cupsOAuthGetMetadata(oauth_uri)) == NULL)
+ {
+ _cupsLangPrintf(stderr, _("cups-oauth: Unable to get metadata for '%s': %s"), oauth_uri, cupsGetErrorString());
+ return (1);
+ }
+
+ // Authorize...
+ if ((auth_code = cupsOAuthGetAuthorizationCode(oauth_uri, metadata, resource_uri, scopes, /*redirect_uri*/NULL)) == NULL)
+ {
+ _cupsLangPrintf(stderr, _("cups-oauth: Unable to get authorization from '%s': %s"), oauth_uri, cupsGetErrorString());
+ goto done;
+ }
+
+ // Get the access token...
+ if ((access_token = cupsOAuthGetTokens(oauth_uri, metadata, resource_uri, auth_code, CUPS_OGRANT_AUTHORIZATION_CODE, CUPS_OAUTH_REDIRECT_URI, &access_expires)) == NULL)
+ {
+ _cupsLangPrintf(stderr, _("cups-oauth: Unable to get access token from '%s': %s"), oauth_uri, cupsGetErrorString());
+ goto done;
+ }
+
+ // Show access token
+ puts(access_token);
+
+ status = 0;
+
+ // Clean up and return...
+ done:
+
+ cupsJSONDelete(metadata);
+ free(auth_code);
+ free(access_token);
+
+ return (status);
+}
+
+
+//
+// 'do_clear()' - Clear authorization information.
+//
+
+static int // O - Exit status
+do_clear(const char *oauth_uri, // I - Authorization Server URI
+ const char *resource_uri) // I - Resource URI
+{
+ cupsOAuthClearTokens(oauth_uri, resource_uri);
+
+ return (0);
+}
+
+
+//
+// 'do_get_access_token()' - Get an access token.
+//
+
+static int // O - Exit status
+do_get_access_token(
+ const char *oauth_uri, // I - Authorization Server URI
+ const char *resource_uri) // I - Resource URI
+{
+ char *access_token; // Access token
+ time_t access_expires; // Expiration date
+
+
+ if ((access_token = cupsOAuthCopyAccessToken(oauth_uri, resource_uri, &access_expires)) != NULL)
+ {
+ puts(access_token);
+ free(access_token);
+ return (0);
+ }
+
+ return (1);
+}
+
+
+//
+// 'do_get_client_id()' - Get the client ID value.
+//
+
+static int // O - Exit status
+do_get_client_id(
+ const char *oauth_uri) // I - Authorization Server URI
+{
+ char *client_id; // Client ID
+
+
+ if ((client_id = cupsOAuthCopyClientId(oauth_uri, CUPS_OAUTH_REDIRECT_URI)) != NULL)
+ {
+ puts(client_id);
+ free(client_id);
+ return (0);
+ }
+
+ return (1);
+}
+
+
+//
+// 'do_get_metadata()' - Get authorization server metadata.
+//
+
+static int // O - Exit status
+do_get_metadata(const char *oauth_uri, // I - Authorization Server URI
+ const char *name) // I - Field name
+{
+ cups_json_t *metadata; // Metadata
+ char *json; // JSON string
+
+
+ // Get the metadata...
+ if ((metadata = cupsOAuthGetMetadata(oauth_uri)) == NULL)
+ {
+ _cupsLangPrintf(stderr, _("cups-oauth: Unable to get metadata for '%s': %s"), oauth_uri, cupsGetErrorString());
+ return (1);
+ }
+
+ // Show metadata...
+ if (name)
+ {
+ cups_json_t *value = cupsJSONFind(metadata, name);
+ // Metadata value
+
+ if (value)
+ {
+ switch (cupsJSONGetType(value))
+ {
+ case CUPS_JTYPE_NULL :
+ puts("null");
+ break;
+
+ case CUPS_JTYPE_FALSE :
+ puts("false");
+ break;
+
+ case CUPS_JTYPE_TRUE :
+ puts("true");
+ break;
+
+ case CUPS_JTYPE_NUMBER :
+ printf("%g\n", cupsJSONGetNumber(value));
+ break;
+
+ case CUPS_JTYPE_STRING :
+ puts(cupsJSONGetString(value));
+ break;
+
+ default :
+ if ((json = cupsJSONExportString(value)) != NULL)
+ {
+ puts(json);
+ free(json);
+ }
+ break;
+ }
+
+ return (0);
+ }
+ else
+ {
+ return (1);
+ }
+ }
+ else if ((json = cupsJSONExportString(metadata)) != NULL)
+ {
+ puts(json);
+ free(json);
+ }
+
+ return (0);
+}
+
+
+//
+// 'do_get_user_id()' - Get user identification.
+//
+
+static int // O - Exit status
+do_get_user_id(
+ const char *oauth_uri, // I - Authorization Server URI
+ const char *resource_uri, // I - Resource URI
+ const char *name) // I - Claim name
+{
+ cups_jwt_t *user_id; // User ID information
+ cups_json_t *claims; // Claims
+ char *json, // JSON string
+ date[256]; // Date
+ int ret = 0; // Exit status
+
+
+ // Get the user_id...
+ if ((user_id = cupsOAuthCopyUserId(oauth_uri, resource_uri)) == NULL)
+ {
+ _cupsLangPrintf(stderr, _("cups-oauth: Unable to get user ID for '%s': %s"), oauth_uri, cupsGetErrorString());
+ return (1);
+ }
+
+ claims = cupsJWTGetClaims(user_id);
+
+ // Show user information...
+ if (name)
+ {
+ cups_json_t *value = cupsJSONFind(claims, name);
+ // Claim value
+
+ if (value)
+ {
+ switch (cupsJSONGetType(value))
+ {
+ case CUPS_JTYPE_NULL :
+ puts("null");
+ break;
+
+ case CUPS_JTYPE_FALSE :
+ puts("false");
+ break;
+
+ case CUPS_JTYPE_TRUE :
+ puts("true");
+ break;
+
+ case CUPS_JTYPE_NUMBER :
+ if (!strcmp(name, "exp") || !strcmp(name, "iat") || !strcmp(name, "nbf"))
+ puts(httpGetDateString2((time_t)cupsJSONGetNumber(value), date, sizeof(date)));
+ else
+ printf("%g\n", cupsJSONGetNumber(value));
+ break;
+
+ case CUPS_JTYPE_STRING :
+ puts(cupsJSONGetString(value));
+ break;
+
+ default :
+ if ((json = cupsJSONExportString(value)) != NULL)
+ {
+ puts(json);
+ free(json);
+ }
+ break;
+ }
+ }
+ else
+ {
+ ret = 1;
+ }
+ }
+ else if ((json = cupsJSONExportString(claims)) != NULL)
+ {
+ puts(json);
+ free(json);
+ }
+
+ cupsJWTDelete(user_id);
+
+ return (ret);
+}
+
+
+//
+// 'do_set_access_token()' - Set the access token.
+//
+
+static int // O - Exit status
+do_set_access_token(
+ const char *oauth_uri, // I - Authorization Server URI
+ const char *resource_uri, // I - Resource URI
+ const char *token) // I - Access token
+{
+ cupsOAuthSaveTokens(oauth_uri, resource_uri, token, /*access_expires*/time(NULL) + 365 * 86400, /*user_id*/NULL, /*refresh_token*/NULL);
+
+ return (0);
+}
+
+
+//
+// 'do_set_client_data()' - Save client_id and client_secret values.
+//
+
+static int // O - Exit status
+do_set_client_data(
+ const char *oauth_uri, // I - Authorization Server URI
+ const char *client_id, // I - Client ID
+ const char *client_secret) // I - Client secret
+{
+ cupsOAuthSaveClientData(oauth_uri, CUPS_OAUTH_REDIRECT_URI, client_id, client_secret);
+
+ return (0);
+}
+
+
+//
+// 'usage()' - Show usage.
+//
+
+static int // O - Exit status
+usage(FILE *out) // I - Output file
+{
+ _cupsLangPuts(out, _("Usage: cups-oauth [OPTIONS] [COMMAND [ARGUMENT(S)]]"));
+ _cupsLangPuts(out, "");
+ _cupsLangPuts(out, _("Commands:"));
+ _cupsLangPuts(out, "");
+ _cupsLangPuts(out, _("authorize [RESOURCE] Authorize access to a resource"));
+ _cupsLangPuts(out, _("clear [RESOURCE] Clear the authorization for a resource"));
+ _cupsLangPuts(out, _("get-access-token [RESOURCE] Get the current access token"));
+ _cupsLangPuts(out, _("get-client-id Get the client ID for the authorization server"));
+ _cupsLangPuts(out, _("get-metadata [NAME] Get metadata from the authorization server"));
+ _cupsLangPuts(out, _("get-user-id [RESOURCE] [NAME] Get the authorized user ID"));
+ _cupsLangPuts(out, _("set-access-token [RESOURCE] TOKEN\n"
+ " Set the current access token"));
+ _cupsLangPuts(out, _("set-client-data CLIENT-ID CLIENT-SECRET\n"
+ " Set the client ID and secret for the authorization server."));
+ _cupsLangPuts(out, "");
+ _cupsLangPuts(out, _("Options:"));
+ _cupsLangPuts(out, "");
+ _cupsLangPuts(out, _("--help Show this help"));
+ _cupsLangPuts(out, _("--version Show the program version"));
+ _cupsLangPuts(out, _("-a OAUTH-URI Specify the OAuth authorization server URL"));
+ _cupsLangPuts(out, _("-s SCOPE(S) Specify the scope(s) to authorize"));
+
+ return (out == stdout ? 0 : 1);
+}