2 * Unix SMB/CIFS implementation.
4 * CUPS printing backend helper to execute smbspool
6 * Copyright (C) 2010-2011 Andreas Schneider <asn@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
24 #include "system/passwd.h"
30 #include <cups/backend.h>
32 #include "dynconfig/dynconfig.h"
36 enum cups_smb_dbglvl_e
{
37 CUPS_SMB_LOG_DEBUG
= 0,
40 static void cups_smb_debug(enum cups_smb_dbglvl_e lvl
, const char *format
, ...);
42 #define CUPS_SMB_DEBUG(...) cups_smb_debug(CUPS_SMB_LOG_DEBUG, __VA_ARGS__)
43 #define CUPS_SMB_ERROR(...) cups_smb_debug(CUPS_SMB_LOG_DEBUG, __VA_ARGS__)
45 static void cups_smb_debug(enum cups_smb_dbglvl_e lvl
, const char *format
, ...)
47 const char *prefix
= "DEBUG";
52 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
56 case CUPS_SMB_LOG_DEBUG
:
59 case CUPS_SMB_LOG_ERROR
:
65 "%s: SMBSPOOL_KRB5 - %s\n",
71 * This is a helper binary to execute smbspool.
73 * It needs to be installed or symlinked as:
74 * /usr/lib/cups/backend/smb
76 * The permissions of the binary need to be set to 0700 so that it is executed
77 * as root. The binary switches to the user which is passed via the environment
78 * variable AUTH_UID, so we can access the kerberos ticket.
80 int main(int argc
, char *argv
[])
82 char smbspool_cmd
[PATH_MAX
] = {0};
84 char gen_cc
[PATH_MAX
] = {0};
87 uid_t uid
= (uid_t
)-1;
88 gid_t gid
= (gid_t
)-1;
93 /* Check if AuthInfoRequired is set to negotiate */
94 env
= getenv("AUTH_INFO_REQUIRED");
96 /* If not set, then just call smbspool. */
98 CUPS_SMB_DEBUG("AUTH_INFO_REQUIRED is not set - "
102 CUPS_SMB_DEBUG("AUTH_INFO_REQUIRED=%s", env
);
104 cmp
= strcmp(env
, "username,password");
106 CUPS_SMB_DEBUG("Authenticate using username/password - "
111 /* if AUTH_INFO_REQUIRED=none */
112 cmp
= strcmp(env
, "negotiate");
114 CUPS_SMB_ERROR("Authentication unsupported");
115 fprintf(stderr
, "ATTR: auth-info-required=negotiate\n");
116 return CUPS_BACKEND_AUTH_REQUIRED
;
122 CUPS_SMB_DEBUG("Started with uid=%d\n", uid
);
128 * AUTH_UID gets only set if we have an incoming connection over the
129 * CUPS unix domain socket.
131 env
= getenv("AUTH_UID");
133 CUPS_SMB_ERROR("AUTH_UID is not set");
134 fprintf(stderr
, "ATTR: auth-info-required=negotiate\n");
135 return CUPS_BACKEND_AUTH_REQUIRED
;
138 if (strlen(env
) > 10) {
139 CUPS_SMB_ERROR("Invalid AUTH_UID");
140 return CUPS_BACKEND_FAILED
;
144 tmp
= strtoul(env
, NULL
, 10);
145 if (errno
!= 0 || tmp
>= UINT32_MAX
) {
146 CUPS_SMB_ERROR("Failed to convert AUTH_UID=%s", env
);
147 return CUPS_BACKEND_FAILED
;
153 CUPS_SMB_ERROR("Failed to find system user: %u - %s",
154 uid
, strerror(errno
));
155 return CUPS_BACKEND_FAILED
;
159 rc
= setgroups(0, NULL
);
161 CUPS_SMB_ERROR("Failed to clear groups - %s",
163 return CUPS_BACKEND_FAILED
;
166 CUPS_SMB_DEBUG("Switching to gid=%d", gid
);
169 CUPS_SMB_ERROR("Failed to switch to gid=%u",
172 return CUPS_BACKEND_FAILED
;
175 CUPS_SMB_DEBUG("Switching to uid=%u", uid
);
178 CUPS_SMB_ERROR("Failed to switch to uid=%u",
181 return CUPS_BACKEND_FAILED
;
184 snprintf(gen_cc
, sizeof(gen_cc
), "/tmp/krb5cc_%d", uid
);
186 rc
= lstat(gen_cc
, &sb
);
188 snprintf(gen_cc
, sizeof(gen_cc
), "FILE:/tmp/krb5cc_%d", uid
);
190 snprintf(gen_cc
, sizeof(gen_cc
), "/run/user/%d/krb5cc", uid
);
192 rc
= lstat(gen_cc
, &sb
);
193 if (rc
== 0 && S_ISDIR(sb
.st_mode
)) {
196 "DIR:/run/user/%d/krb5cc",
199 #if defined(__linux__)
202 "KEYRING:persistent:%d",
209 * Make sure we do not have LD_PRELOAD or other security relevant
210 * environment variables set.
216 extern char **environ
;
217 environ
= calloc(1, sizeof(*environ
));
221 CUPS_SMB_DEBUG("Setting KRB5CCNAME to '%s'", gen_cc
);
222 setenv("KRB5CCNAME", gen_cc
, 1);
225 snprintf(smbspool_cmd
,
226 sizeof(smbspool_cmd
),
230 return execv(smbspool_cmd
, argv
);