Viewing: l_getauth.c
#include <sys/types.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <glob.h>
#include <getopt.h>
#include "lsupport.h"
#include "err_util.h"
static int start_daemon(char *auth_req)
{
int rc;
rc = system("/usr/bin/systemctl restart lsvcgss");
if (rc < 0 || (errno = WEXITSTATUS(rc))) {
printerr(LL_ERR, "systemctl restart lsvcgss service failed: %s\n",
strerror(errno));
rc = -errno;
} else {
printerr(LL_INFO, "lsvcgss service automatically restarted\n");
rc = 0;
}
return rc;
}
int main(int argc, char **argv)
{
int local_socket;
struct sockaddr_un addr;
ssize_t bytes_sent;
char *auth_req = NULL, *cachename = NULL;
ssize_t req_len;
int opt, debug = 0, tried_daemon = 0, rc = 0;
/* Parameters received from kernel (see rsi_do_upcall()):
* -c <cache name> -r <auth request> -d
* -d checks connection to lsvcgssd daemon
*/
static struct option long_opts[] = {
{ .name = "cache", .has_arg = required_argument, .val = 'c'},
{ .name = "debug", .has_arg = no_argument, .val = 'd'},
{ .name = "authreq", .has_arg = required_argument, .val = 'r'},
{ .name = NULL, } };
/* init gss logger for foreground (stderr) or background (syslog) */
initerr(NULL, LL_MAX, isatty(STDOUT_FILENO));
while ((opt = getopt_long(argc, argv, "c:dr:",
long_opts, NULL)) != EOF) {
switch (opt) {
case 'c':
cachename = optarg;
break;
case 'd':
debug = 1;
goto socket;
case 'r':
auth_req = optarg;
break;
default:
printerr(LL_ERR, "error: unknown option: '%c'\n", opt);
return EXIT_FAILURE;
}
}
if (optind != argc) {
printerr(LL_ERR,
"error: extraneous arguments provided, check usage\n");
return EXIT_FAILURE;
}
if (!cachename || !auth_req) {
printerr(LL_ERR, "error: missing arguments, check usage\n");
return EXIT_FAILURE;
}
if (strcmp(cachename, RSI_CACHE_NAME) != 0) {
printerr(LL_ERR, "invalid cache name %s\n", cachename);
return EXIT_FAILURE;
}
req_len = strlen(auth_req);
socket:
/* Send auth request to lsvcgssd via a socket. */
local_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (local_socket == -1) {
printerr(LL_ERR, "cannot create socket: %d\n", -errno);
return EXIT_FAILURE;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, GSS_SOCKET_PATH, sizeof(addr.sun_path) - 1);
connect:
if (connect(local_socket, (struct sockaddr *)&addr,
sizeof(addr)) == -1) {
rc = -errno;
printerr(LL_ERR, "cannot connect to socket: %d\n", rc);
if (debug || tried_daemon == 5)
goto out;
if (!tried_daemon) {
rc = start_daemon(auth_req);
if (rc) {
rc = -1;
goto out;
}
sleep(2);
}
tried_daemon++;
goto connect;
}
if (debug)
goto out;
bytes_sent = write(local_socket, auth_req, req_len);
if (bytes_sent < 0) {
rc = -errno;
printerr(LL_ERR, "write failed: %d\n", rc);
} else if (bytes_sent != req_len) {
printerr(LL_ERR, "partial write %zu vs. %zu\n",
bytes_sent, req_len);
rc = -EMSGSIZE;
}
out:
close(local_socket);
return rc < 0 ? EXIT_FAILURE : 0;
}