550N/A/*
1546N/A *
1546N/A * mkcookie.c 1.x
1546N/A *
1546N/A * Copyright (c) 1990, 2015, Oracle and/or its affiliates. All rights reserved.
1546N/A *
1546N/A * Permission is hereby granted, free of charge, to any person obtaining a
1546N/A * copy of this software and associated documentation files (the "Software"),
1546N/A * to deal in the Software without restriction, including without limitation
1546N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1546N/A * and/or sell copies of the Software, and to permit persons to whom the
1546N/A * Software is furnished to do so, subject to the following conditions:
1546N/A *
1546N/A * The above copyright notice and this permission notice (including the next
1546N/A * paragraph) shall be included in all copies or substantial portions of the
1546N/A * Software.
1546N/A *
1546N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1546N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1546N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1546N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1546N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1546N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1546N/A * DEALINGS IN THE SOFTWARE.
1546N/A *
1546N/A */
550N/A
550N/A/*
550N/A * $XConsortium: auth.c,v 1.17 89/12/14 09:42:18 rws Exp $
550N/A *
550N/A * Copyright 1988 Massachusetts Institute of Technology
550N/A *
550N/A * Permission to use, copy, modify, and distribute this software and its
550N/A * documentation for any purpose and without fee is hereby granted, provided
550N/A * that the above copyright notice appear in all copies and that both that
550N/A * copyright notice and this permission notice appear in supporting
550N/A * documentation, and that the name of M.I.T. not be used in advertising or
550N/A * publicity pertaining to distribution of the software without specific,
550N/A * written prior permission. M.I.T. makes no representations about the
550N/A * suitability of this software for any purpose. It is provided "as is"
550N/A * without express or implied warranty.
550N/A *
550N/A * Author: Keith Packard, MIT X Consortium
550N/A */
550N/A
550N/A#include <stdio.h>
1546N/A#include <stdlib.h>
1546N/A#include <stdarg.h>
1546N/A#include <errno.h>
550N/A#include <sys/types.h>
550N/A#include <sys/stat.h>
550N/A#include <sys/ioctl.h>
550N/A#include <sys/socket.h>
550N/A#include <sys/sockio.h>
550N/A#include <netinet/in.h>
550N/A#include <net/if.h>
1546N/A#include <netdb.h>
550N/A#include <X11/X.h>
550N/A#include <X11/Xauth.h>
550N/A#include <X11/Xos.h>
550N/A#include <rpc/rpc.h>
1546N/A#include <sys/random.h>
1546N/A
1546N/A#define AUTH_DATA_LEN 16 /* bytes of MIT-MAGIC-COOKIE data */
1546N/A#define DEF_USER_AUTH_DIR "/tmp" /* Backup directory for User Auth file */
550N/A
1546N/Astatic void setAuthNumber(Xauth *auth, const char *name);
1546N/Astatic void DefineLocal(FILE *file, Xauth *auth);
1546N/Astatic void DefineSelf(int fd, FILE *file, Xauth *auth);
1546N/Astatic void writeAuth(FILE *file, Xauth *auth);
1546N/Astatic void GenerateCryptoKey(char *auth, int len);
550N/A
550N/Astruct display {
1546N/A char * name; /* DISPLAY name */
1546N/A Xauth * authorization; /* authorization data */
1546N/A char * authFile; /* file to store authorization in */
1546N/A const char *userAuthDir; /* backup directory for tickets */
1546N/A const char *authName; /* authorization protocol name */
550N/A};
550N/A
550N/Astruct verify_info {
1546N/A uid_t uid; /* user id */
1546N/A gid_t gid; /* group id */
550N/A};
550N/A
550N/Astruct addrList {
1546N/A unsigned short family;
1546N/A unsigned short address_length;
1546N/A unsigned short number_length;
1546N/A char * address;
1546N/A char * number;
1546N/A struct addrList * next;
550N/A};
550N/A
1546N/Astatic struct addrList *addrs;
1546N/A
1546N/Astatic const char *programName;
550N/A
1546N/A/* PRINTFLIKE1 */
1546N/Astatic void _X_NORETURN _X_ATTRIBUTE_PRINTF(1, 2)
1546N/AfatalError(const char *msg, ...)
1546N/A{
1546N/A va_list args;
550N/A
1546N/A fflush(stdout);
1546N/A fflush(stderr);
1546N/A fprintf(stderr, "%s: error: ", programName);
1546N/A
1546N/A va_start(args, msg);
1546N/A vfprintf(stderr, msg, args);
1546N/A va_end(args);
1546N/A
1546N/A fprintf(stderr, "\n");
1546N/A exit(EXIT_FAILURE);
550N/A}
550N/A
1546N/Astatic int
1546N/AbinaryEqual(const char *a, const char *b, int len)
550N/A{
1546N/A while (len-- > 0)
1546N/A if (*a++ != *b++)
1546N/A return 0;
1546N/A return 1;
550N/A}
550N/A
550N/A#ifdef DEBUG
1233N/Astatic void
1546N/AdumpBytes(int len, const char *data)
1546N/A{
1546N/A int i;
1546N/A
1546N/A printf("%d: ", len);
1546N/A for (i = 0; i < len; i++)
1546N/A printf("%02x ", data[i] & 0377);
1546N/A printf("\n");
1546N/A}
1546N/A
1546N/Astatic void
1546N/AdumpAuth(Xauth *auth)
550N/A{
1546N/A printf("family: %d\n", auth->family);
1546N/A printf("addr: ");
1546N/A dumpBytes(auth->address_length, auth->address);
1546N/A printf("number: ");
1546N/A dumpBytes(auth->number_length, auth->number);
1546N/A printf("name: ");
1546N/A dumpBytes(auth->name_length, auth->name);
1546N/A printf("data: ");
1546N/A dumpBytes(auth->data_length, auth->data);
1546N/A}
1546N/A#endif /* DEBUG */
1546N/A
1546N/Astatic int
1546N/AcheckAddr(unsigned short family,
1546N/A unsigned short address_length, const char *address,
1546N/A unsigned short number_length, const char *number)
1546N/A{
1546N/A struct addrList *a;
1546N/A
1546N/A for (a = addrs; a != NULL; a = a->next) {
1546N/A if (a->family == family &&
1546N/A a->address_length == address_length &&
1546N/A binaryEqual(a->address, address, address_length) &&
1546N/A a->number_length == number_length &&
1546N/A binaryEqual(a->number, number, number_length)) {
1546N/A return 1;
1546N/A }
1546N/A }
1546N/A return 0;
550N/A}
550N/A
1233N/Astatic void
1546N/AsaveAddr(unsigned short family,
1546N/A unsigned short address_length, const char *address,
1546N/A unsigned short number_length, const char *number)
550N/A{
1546N/A struct addrList *new;
550N/A
1546N/A if (checkAddr(family, address_length, address, number_length, number))
1546N/A return;
1546N/A new = calloc(1, sizeof(struct addrList));
1546N/A if (new == NULL) {
1546N/A perror("saveAddr");
1546N/A return;
1546N/A }
1546N/A if ((new->address_length = address_length) > 0) {
1546N/A new->address = malloc(address_length);
1546N/A if (new->address == NULL) {
1546N/A goto fail;
1546N/A }
1546N/A memcpy(new->address, address, (size_t) address_length);
1546N/A }
1546N/A else
1546N/A new->address = NULL;
1546N/A if ((new->number_length = number_length) > 0) {
1546N/A new->number = malloc(number_length);
1546N/A if (new->number == NULL) {
1546N/A goto fail;
1546N/A }
1546N/A memcpy(new->number, number, (size_t) number_length);
1546N/A }
1546N/A else
1546N/A new->number = NULL;
1546N/A new->family = family;
1546N/A new->next = addrs;
1546N/A addrs = new;
1546N/A return;
1546N/A
1546N/A fail:
1546N/A perror("saveAddr");
1546N/A free(new->address);
1546N/A free(new);
1546N/A return;
550N/A}
550N/A
1233N/Astatic void
1546N/AwriteLocalAuth(FILE *file, Xauth *auth, const char *name)
550N/A{
1546N/A int fd;
1546N/A
1546N/A setAuthNumber(auth, name);
1546N/A fd = socket(PF_INET6, SOCK_STREAM, 0);
1546N/A DefineSelf(fd, file, auth);
1546N/A close(fd);
1546N/A
1546N/A DefineLocal(file, auth);
1546N/A}
1546N/A
1546N/Astatic void
1546N/AwriteAddr(int family, size_t addr_length, char *addr, FILE *file, Xauth *auth)
1546N/A{
1546N/A auth->family = (unsigned short) family;
1546N/A auth->address_length = (unsigned short) addr_length;
1546N/A auth->address = addr;
1546N/A#ifdef DEBUG
1546N/A printf("--- writeAddr:\n");
1546N/A dumpAuth(auth);
1546N/A#endif
1546N/A writeAuth(file, auth);
550N/A}
550N/A
1233N/Astatic void
1546N/ADefineSelf(int fd, FILE *file, Xauth *auth)
550N/A{
1546N/A char buf[2048] = { 0 };
1546N/A void * bufptr = buf;
1546N/A size_t len = sizeof(buf);
1546N/A char * addr;
1546N/A int n;
1546N/A int family;
1546N/A struct lifreq * ifr;
1546N/A struct lifnum ifn = { .lifn_family = AF_UNSPEC, .lifn_flags = 0 };
1546N/A struct lifconf ifc = { .lifc_family = AF_UNSPEC, .lifc_flags = 0 };
1546N/A
1546N/A if (ioctl(fd, (int) SIOCGLIFNUM, &ifn) < 0) {
1546N/A perror("Getting interface count");
1546N/A }
1546N/A else if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
1546N/A len = ifn.lifn_count * sizeof(struct lifreq);
1546N/A bufptr = malloc(len);
1546N/A }
1546N/A
1546N/A ifc.lifc_len = (int) len;
1546N/A ifc.lifc_buf = bufptr;
1546N/A if (ioctl(fd, (int) SIOCGLIFCONF, &ifc) < 0) {
1546N/A perror("Getting interface list");
1546N/A return;
1546N/A }
1546N/A for (ifr = ifc.lifc_req, n = ifc.lifc_len / (int) sizeof(struct lifreq);
1546N/A --n >= 0; ifr++) {
1546N/A struct sockaddr *saddr = (struct sockaddr *) &ifr->lifr_addr;
550N/A
1546N/A switch (saddr->sa_family) {
1546N/A case AF_INET:
1546N/A /*
1546N/A * If we get back a 0.0.0.0 IP address, ignore this entry.
1546N/A * This typically happens when a machine is in a standalone mode.
1546N/A */
1546N/A addr = (char *) &(((struct sockaddr_in *) saddr)->sin_addr);
1546N/A if (addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0)
1546N/A continue;
1546N/A family = FamilyInternet;
1546N/A len = sizeof(struct in_addr);
1546N/A break;
550N/A
1546N/A case AF_INET6:
1546N/A addr = (char *) &(((struct sockaddr_in6 *) saddr)->sin6_addr);
1546N/A if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *) addr)))
1546N/A continue;
1546N/A family = FamilyInternet6;
1546N/A len = sizeof(struct in6_addr);
1546N/A break;
550N/A
1546N/A default:
1546N/A continue;
1546N/A }
550N/A
1546N/A writeAddr(family, len, addr, file, auth);
1546N/A }
550N/A}
550N/A
1233N/Astatic void
1546N/ADefineLocal(FILE *file, Xauth *auth)
550N/A{
1546N/A char displayname[MAXHOSTNAMELEN];
1546N/A
1546N/A if (gethostname(displayname, sizeof(displayname)) == 0)
1546N/A writeAddr(FamilyLocal, strlen(displayname), displayname, file, auth);
1546N/A else
1546N/A perror("gethostname");
550N/A}
550N/A
1546N/Astatic void
1546N/AsetAuthNumber(Xauth *auth, const char *name)
1546N/A{
1546N/A const char *colon;
1546N/A const char *dot;
1546N/A char *number;
1546N/A
1546N/A colon = strrchr(name, ':');
1546N/A if (colon) {
1546N/A ++colon;
1546N/A if ((dot = strchr(colon, '.')))
1546N/A auth->number_length = (unsigned short) (dot - colon);
1546N/A else
1546N/A auth->number_length = (unsigned short) strlen(colon);
1546N/A number = malloc(auth->number_length + 1);
1546N/A if (number) {
1546N/A strncpy(number, colon, auth->number_length);
1546N/A number[auth->number_length] = '\0';
1546N/A }
1546N/A else {
1546N/A perror("setAuthNumber");
1546N/A auth->number_length = 0;
1546N/A }
1546N/A auth->number = number;
1546N/A }
1546N/A}
550N/A
550N/Astatic int
1546N/AopenFiles(const char *name, char *new_name, size_t new_name_size,
1546N/A FILE ** oldp, FILE ** newp)
550N/A{
1546N/A int newfd;
1546N/A
1546N/A snprintf(new_name, new_name_size, "%s-n", name);
1546N/A (void) remove(new_name);
1546N/A newfd = open(new_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
1546N/A if (newfd == -1) {
1546N/A perror(new_name);
1546N/A return 0;
550N/A }
1546N/A *newp = fdopen(newfd, "w");
1546N/A if (*newp == NULL) {
1546N/A perror(new_name);
1546N/A close(newfd);
1546N/A (void) remove(new_name);
1546N/A return 0;
1546N/A }
1546N/A *oldp = fopen(name, "r");
1546N/A
1546N/A return 1;
1546N/A}
1546N/A
1546N/Astatic void
1546N/AwriteAuth(FILE *file, Xauth *auth)
1546N/A{
1546N/A saveAddr(auth->family, auth->address_length, auth->address,
1546N/A auth->number_length, auth->number);
1546N/A if (!XauWriteAuth(file, auth)) {
1546N/A fatalError("Could not write authorization info. for user. exiting");
1546N/A }
550N/A}
550N/A
1233N/Astatic void
1546N/AdoneAddrs(void)
550N/A{
1546N/A struct addrList *a, *n;
550N/A
1546N/A for (a = addrs; a != NULL; a = n) {
1546N/A n = a->next;
1546N/A free(a->address);
1546N/A free(a->number);
1546N/A free(a);
1546N/A }
1546N/A addrs = NULL;
550N/A}
550N/A
1233N/Astatic Xauth *
1546N/AGenerateAuthorization(const char *name)
550N/A{
1546N/A Xauth *new;
1546N/A
1546N/A new = calloc(1, sizeof(Xauth));
1546N/A if (new == NULL) {
1546N/A goto fail;
1546N/A }
1546N/A new->family = FamilyWild;
1546N/A
1546N/A if (strcmp(name, "MIT-MAGIC-COOKIE-1") == 0) {
1546N/A new->data = malloc(AUTH_DATA_LEN);
1546N/A if (new->data == NULL) {
1546N/A goto fail;
1546N/A }
1546N/A GenerateCryptoKey(new->data, AUTH_DATA_LEN);
1546N/A new->data_length = AUTH_DATA_LEN;
550N/A }
1546N/A else if (strcmp(name, "SUN-DES-1") == 0) {
1546N/A char netname[MAXNETNAMELEN + 1] = "";
1546N/A uid_t uid = getuid();
1546N/A
1546N/A if (!user2netname(netname, uid, 0)) {
1546N/A goto fail;
1546N/A }
1546N/A new->data = strdup(netname);
1546N/A if (new->data == NULL) {
1546N/A goto fail;
1546N/A }
1546N/A new->data_length = (unsigned short) strlen(netname);
550N/A }
1546N/A else {
1546N/A fprintf(stderr, "%s: unsupported authorization protocol '%s'\n",
1546N/A programName, name);
1546N/A goto fail;
1546N/A }
1546N/A
1546N/A new->name = strdup(name);
1546N/A if (new->name == NULL) {
1546N/A goto fail;
1546N/A }
1546N/A new->name_length = (unsigned short) strlen(name);
1546N/A return new;
1546N/A
1546N/A fail:
1546N/A perror("GenerateAuthorization");
1546N/A if (new != NULL) {
1546N/A free(new->data);
1546N/A free(new);
1546N/A }
1546N/A return (Xauth *) NULL;
1546N/A
550N/A}
550N/A
1233N/Astatic void
1546N/AGenerateCryptoKey(char *auth, int len)
550N/A{
1546N/A int needed = len;
1546N/A int received = 0;
1546N/A
1546N/A while (needed > 0) {
1546N/A int result = getrandom(auth + received, needed, GRND_RANDOM);
550N/A
1546N/A if (result == -1) {
1546N/A if ((errno != EAGAIN) && (errno != EINTR)) {
1546N/A perror("getrandom");
1546N/A break;
1546N/A }
1546N/A }
1546N/A else {
1546N/A needed -= result;
1546N/A received += result;
1546N/A }
1546N/A }
1546N/A
1546N/A if (needed > 0) { /* fallback if getrandom returns non-retryable error */
1546N/A struct timeval now;
1546N/A int seed;
1546N/A int i;
1546N/A
1546N/A gettimeofday(&now, NULL);
1546N/A seed = (int) (now.tv_sec + (now.tv_usec << 16));
1546N/A srand(seed);
1546N/A
1546N/A for (i = received; i < len; i++) {
1546N/A int value = rand();
1546N/A auth[i] = (char) (value & 0xff);
1546N/A }
1546N/A }
550N/A}
550N/A
1233N/Astatic int
1546N/ASaveServerAuthorization(const char *authFile, Xauth *auth)
550N/A{
1546N/A FILE *auth_file;
1546N/A int auth_fd;
1546N/A int ret;
1546N/A
1546N/A (void) remove(authFile);
1546N/A auth_fd = open(authFile, O_WRONLY | O_CREAT | O_EXCL, 0600);
1546N/A if (auth_fd == -1) {
1546N/A perror(authFile);
1546N/A return FALSE;
550N/A }
1546N/A
1546N/A auth_file = fdopen(auth_fd, "w");
1546N/A if (auth_file == NULL) {
1546N/A perror(authFile);
1546N/A close(auth_fd);
1546N/A (void) remove(authFile);
1546N/A ret = FALSE;
1546N/A }
1546N/A else {
1546N/A if (!XauWriteAuth(auth_file, auth) || (fflush(auth_file) == EOF)) {
1546N/A ret = FALSE;
1546N/A }
1546N/A else {
1546N/A ret = TRUE;
1546N/A }
1546N/A fchmod(auth_fd, S_IREAD);
1546N/A fclose(auth_file);
1546N/A }
1546N/A return ret;
550N/A}
550N/A
1546N/Astatic void
1546N/ASetLocalAuthorization(struct display *d)
550N/A{
1546N/A Xauth *auth;
550N/A
1546N/A if (d->authorization) {
1546N/A XauDisposeAuth(d->authorization);
1546N/A d->authorization = (Xauth *) NULL;
550N/A }
1546N/A auth = GenerateAuthorization(d->authName);
1546N/A if (auth == NULL)
1546N/A return;
1546N/A
1546N/A /* Change to real user id, before writing any files */
1546N/A setuid(getuid());
1546N/A
1546N/A if (SaveServerAuthorization(d->authFile, auth)) {
1546N/A d->authorization = auth;
1546N/A }
1546N/A else {
1546N/A XauDisposeAuth(auth);
1546N/A fatalError("Could not write server authorization file. exiting");
1546N/A }
550N/A}
550N/A
1233N/Astatic void
1546N/ASetUserAuthorization(struct display *d, struct verify_info *verify)
550N/A{
1546N/A FILE *old = NULL, *new = NULL;
1546N/A char home_name[1024], backup_name[1024], new_name[1024];
1546N/A char *name = NULL;
1546N/A char *home;
1546N/A char *envname;
1546N/A int lockStatus;
1546N/A Xauth *entry, *auth;
1546N/A struct stat statb;
1546N/A
1546N/A new_name[0] = '\0';
1546N/A
1546N/A if ((auth = d->authorization) != NULL) {
1546N/A home = getenv("HOME");
1546N/A lockStatus = LOCK_ERROR;
1546N/A if (home) {
1546N/A snprintf(home_name, sizeof(home_name), "%s/.Xauthority", home);
1546N/A lockStatus = XauLockAuth(home_name, 1, 2, 10);
1546N/A if (lockStatus == LOCK_SUCCESS) {
1546N/A if (openFiles
1546N/A (home_name, new_name, sizeof(new_name), &old, &new)) {
1546N/A name = home_name;
1546N/A }
1546N/A else {
1546N/A XauUnlockAuth(home_name);
1546N/A lockStatus = LOCK_ERROR;
1546N/A }
1546N/A }
1546N/A }
1546N/A if (lockStatus != LOCK_SUCCESS) {
1546N/A int tmpfd;
1546N/A
1546N/A snprintf(backup_name, sizeof(backup_name), "%s/.XauthXXXXXX",
1546N/A d->userAuthDir);
1546N/A tmpfd = mkstemp(backup_name);
1546N/A lockStatus = XauLockAuth(backup_name, 1, 2, 10);
550N/A
1546N/A if (lockStatus == LOCK_SUCCESS) {
1546N/A if (openFiles
1546N/A (backup_name, new_name, sizeof(new_name), &old, &new)) {
1546N/A name = backup_name;
1546N/A }
1546N/A else {
1546N/A XauUnlockAuth(backup_name);
1546N/A lockStatus = LOCK_ERROR;
1546N/A }
1546N/A }
1546N/A close(tmpfd);
1546N/A }
1546N/A if (lockStatus != LOCK_SUCCESS) {
1546N/A return;
1546N/A }
1546N/A addrs = NULL;
1546N/A writeLocalAuth(new, auth, d->name);
1546N/A
1546N/A if (old) {
1546N/A if (fstat(fileno(old), &statb) != -1)
1546N/A fchmod(fileno(new), statb.st_mode & 0777);
1546N/A while ((entry = XauReadAuth(old))) {
1546N/A if (!checkAddr(entry->family,
1546N/A entry->address_length, entry->address,
1546N/A entry->number_length, entry->number)) {
1546N/A writeAuth(new, entry);
1546N/A }
1546N/A XauDisposeAuth(entry);
1546N/A }
1546N/A fclose(old);
1546N/A }
1546N/A doneAddrs();
1546N/A fclose(new);
1546N/A remove(name);
1546N/A
1546N/A envname = name;
1546N/A if (link(new_name, name) == -1) {
1546N/A envname = new_name;
1546N/A }
1546N/A else {
1546N/A remove(new_name);
1546N/A }
1546N/A XauUnlockAuth(name);
1546N/A if (envname) {
1546N/A chown(envname, verify->uid, verify->gid);
1546N/A }
550N/A }
550N/A
550N/A}
550N/A
1233N/Astatic void
1233N/Ausage(const char *str)
550N/A{
1546N/A fprintf(stderr, "usage: %s Server_auth_file [-auth protocol]\n", str);
1546N/A fprintf(stderr, " where protocol is one of magic-cookie or sun-des\n");
550N/A}
550N/A
1233N/Aint
1233N/Amain(int argc, char *argv[])
550N/A{
1546N/A struct display d = {
1546N/A .authorization = NULL,
1546N/A .userAuthDir = DEF_USER_AUTH_DIR,
1546N/A .authName = "MIT-MAGIC-COOKIE-1"
1546N/A };
1546N/A struct verify_info verify;
1546N/A const char *au_name = NULL;
550N/A
1546N/A programName = argv[0];
550N/A
1546N/A if ((argc < 2) || (strcmp(argv[1], "--help") == 0)) {
1546N/A usage(argv[0]);
1546N/A fprintf(stderr, "\n"
1546N/A "WARNING: This program will overwrite existing files.\n"
1546N/A "This may cause your X server to not accept any"
1546N/A " new client connections.\n");
1546N/A exit((argc < 2) ? -1 : 0);
1546N/A }
550N/A
1546N/A d.authFile = argv[1];
1546N/A
1546N/A if ((d.name = strrchr(d.authFile, ':')) == NULL) {
1546N/A fatalError("Invalid filename: %s\n"
1546N/A "Filename should include display",
1546N/A d.authFile);
1546N/A }
550N/A
1546N/A if (argv[2] && strcmp(argv[2], "-auth") == 0) {
1546N/A if (argv[3]) {
1546N/A au_name = argv[3];
1546N/A }
1546N/A else {
1546N/A fprintf(stderr, "%s: -auth requires an argument\n", argv[0]);
1546N/A usage(argv[0]);
1546N/A exit(-1);
1546N/A }
550N/A }
1546N/A else if (argv[2]) {
1546N/A fprintf(stderr, "%s: unrecognized option %s\n", argv[0], argv[2]);
1546N/A usage(argv[0]);
1546N/A exit(-1);
1546N/A }
550N/A
1546N/A if (au_name) {
1546N/A if (strcmp(au_name, "sun-des") == 0) {
1546N/A d.authName = "SUN-DES-1";
1546N/A }
1546N/A else if (strncmp(au_name, "magic", 5) != 0) {
1546N/A fprintf(stderr, "%s: -auth: unrecognized protocol %s\n", argv[0],
1546N/A au_name);
1546N/A usage(argv[0]);
1546N/A exit(-1);
1546N/A }
550N/A }
1546N/A
1546N/A verify.uid = getuid();
1546N/A verify.gid = getgid();
550N/A
1546N/A SetLocalAuthorization(&d);
1546N/A SetUserAuthorization(&d, &verify);
1546N/A exit(0);
550N/A}