550N/A/*
550N/A*
550N/A* mkcookie.c 1.x
550N/A*
1233N/A* Copyright (c) 1990, 2011, Oracle and/or its affiliates. All rights reserved.
550N/A*
550N/A* Permission is hereby granted, free of charge, to any person obtaining a
919N/A* copy of this software and associated documentation files (the "Software"),
919N/A* to deal in the Software without restriction, including without limitation
919N/A* the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A* and/or sell copies of the Software, and to permit persons to whom the
919N/A* Software is furnished to do so, subject to the following conditions:
550N/A*
919N/A* The above copyright notice and this permission notice (including the next
919N/A* paragraph) shall be included in all copies or substantial portions of the
919N/A* Software.
550N/A*
919N/A* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A* DEALINGS IN THE SOFTWARE.
550N/A*
550N/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>
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>
550N/A#include <X11/X.h>
550N/A#include <X11/Xauth.h>
550N/A#include <X11/Xos.h>
550N/A#include <rpc/rpc.h>
550N/A#ifdef SYSV
550N/A#include <sys/stropts.h>
550N/A#ifndef bcopy
550N/A#define bcopy(a,b,c) memmove(b,a,c)
550N/A#endif
550N/A#ifndef bzero
550N/A#define bzero(a,b) memset(a,0,b)
550N/A#endif
550N/A#ifndef bcmp
550N/A#define bcmp(a,b,c) memcmp(a,b,c)
550N/A#endif
550N/A#ifndef index
550N/A#define index(a,b) strchr(a,b)
550N/A#endif
550N/A#ifndef rindex
550N/A#define rindex(a,b) strrchr(a,b)
550N/A#endif
550N/A#endif
550N/A
550N/A#define AUTH_DATA_LEN 16 /* bytes of authorization data */
550N/A/* 1191081: SIGSEGV when starting openwin - core dumped by mkcookie.
550N/A * becuase d.userAuthDir is not assigned any valid directory where
550N/A * every one will have access to it.
550N/A */
550N/A#define DEF_USER_AUTH_DIR "/tmp" /* Backup directory for User Auth file */
550N/A
550N/A#include <stdlib.h>
550N/A
1233N/Astatic void setAuthNumber (Xauth *auth, char *name);
1233N/Astatic void DefineLocal (FILE *file, Xauth *auth);
1233N/Astatic void DefineSelf (int fd, FILE *file, Xauth *auth);
1233N/Astatic void writeAuth (FILE *file, Xauth *auth);
1233N/Astatic int ConvertAddr (register struct sockaddr *saddr, int *len, char **addr);
1233N/Astatic void InitAuth (unsigned short name_len, const char *name);
1233N/Astatic Xauth *GetAuth (int namelen, const char *name);
1233N/Astatic void GenerateCryptoKey (char *auth, int len);
1233N/A
550N/A#define Local 1
550N/A#define Foreign 0
550N/A
550N/Atypedef struct displayType {
550N/A unsigned int location:1;
550N/A unsigned int lifetime:1;
550N/A unsigned int origin:1;
550N/A} DisplayType;
550N/A
550N/Astruct display {
550N/A char *name; /* DISPLAY name */
550N/A int authorize; /* enable authorization */
550N/A Xauth *authorization; /* authorization data */
550N/A char *authFile; /* file to store authorization in */
1233N/A const char *userAuthDir; /* backup directory for tickets */
1233N/A const char *authName; /* authorization protocol name */
550N/A int authNameLen; /* authorization protocol name len */
550N/A int resetForAuth; /* server reads auth file at reset */
550N/A DisplayType displayType;
550N/A struct sockaddr *peer;
550N/A int peerlen;
550N/A};
550N/A
550N/Astruct verify_info {
550N/A int uid; /* user id */
550N/A int gid; /* group id */
550N/A char **argv; /* arguments to session */
550N/A char **userEnviron; /* environment for session */
550N/A char **systemEnviron;/* environment for startup/reset */
550N/A};
550N/A
550N/Astruct AuthProtocol {
550N/A int name_length;
1233N/A const char *name;
1233N/A void (*InitAuth)(unsigned short, const char *);
1233N/A Xauth * (*GetAuth)(int, const char *);
550N/A int (*GetXdmcpAuth)();
550N/A int inited;
550N/A};
550N/A
550N/Astruct addrList {
550N/A unsigned short family;
550N/A unsigned short address_length;
550N/A char *address;
550N/A unsigned short number_length;
550N/A char *number;
550N/A struct addrList *next;
550N/A};
550N/A
550N/Astatic char auth_name[256];
550N/Astatic int auth_name_len;
550N/Astatic struct addrList *addrs;
550N/A
550N/Astatic struct AuthProtocol AuthProtocols[] = {
550N/A { (int) 18, "MIT-MAGIC-COOKIE-1",
550N/A InitAuth, GetAuth, NULL,
550N/A },
550N/A { (int) 9, "SUN-DES-1",
550N/A InitAuth, GetAuth, NULL,
550N/A }
550N/A};
550N/A
1233N/Astatic char *
1233N/AmakeEnv (const char *name, const char *value)
550N/A{
550N/A char *result;
550N/A
550N/A result = malloc ((unsigned) (strlen (name) + strlen (value) + 2));
550N/A if (!result) {
550N/A perror ("makeEnv");
550N/A return 0;
550N/A }
550N/A sprintf (result, "%s=%s", name, value);
550N/A return result;
550N/A}
550N/A
550N/A
1233N/Astatic char **
1233N/AsetEnv (char **e,
1233N/A const char *name,
1233N/A const char *value)
550N/A{
550N/A char **new, **old;
550N/A char *newe;
550N/A int envsize;
550N/A int l;
550N/A
550N/A l = strlen (name);
550N/A newe = makeEnv (name, value);
550N/A if (!newe) {
550N/A perror ("setEnv");
550N/A return e;
550N/A }
550N/A if (e) {
550N/A for (old = e; *old; old++)
550N/A if (strlen (*old) > l &&
550N/A !strncmp (*old, name, l) && (*old)[l] == '=')
550N/A break;
550N/A if (*old) {
550N/A free (*old);
550N/A *old = newe;
550N/A return e;
550N/A }
550N/A envsize = old - e;
550N/A new = (char **) realloc ((char *) e,
550N/A (unsigned) ((envsize + 2) * sizeof (char *)));
550N/A } else {
550N/A envsize = 0;
550N/A new = (char **) malloc (2 * sizeof (char *));
550N/A }
550N/A if (!new) {
550N/A perror ("setEnv");
550N/A free (newe);
550N/A return e;
550N/A }
550N/A new[envsize] = newe;
550N/A new[envsize+1] = 0;
550N/A return new;
550N/A}
550N/A
550N/A
1233N/Astatic int
1233N/AbinaryEqual (const char *a, const char *b, int len)
550N/A{
550N/A while (len-- > 0)
550N/A if (*a++ != *b++)
550N/A return 0;
550N/A return 1;
550N/A}
550N/A
550N/A#ifdef DEBUG
1233N/Astatic void
1233N/AdumpBytes (int len, const char *data)
550N/A{
550N/A int i;
550N/A
550N/A printf ("%d: ", len);
550N/A for (i = 0; i < len; i++)
550N/A printf ("%02x ", data[i] & 0377);
550N/A printf ("\n");
550N/A}
550N/A
1233N/Astatic void
1233N/AdumpAuth (Xauth *auth)
550N/A{
550N/A printf ("family: %d\n", auth->family);
550N/A printf ("addr: ");
550N/A dumpBytes (auth->address_length, auth->address);
550N/A printf ("number: ");
550N/A dumpBytes (auth->number_length, auth->number);
550N/A printf ("name: ");
550N/A dumpBytes (auth->name_length, auth->name);
550N/A printf ("data: ");
550N/A dumpBytes (auth->data_length, auth->data);
550N/A}
550N/A
550N/A
550N/A#endif
550N/A
1233N/Astatic int
1233N/AcheckAddr (int family,
1233N/A unsigned short address_length, const char *address,
1233N/A unsigned short number_length, const char *number)
550N/A{
550N/A struct addrList *a;
550N/A
550N/A for (a = addrs; a; a = a->next) {
550N/A if (a->family == family &&
550N/A a->address_length == address_length &&
550N/A binaryEqual (a->address, address, address_length) &&
550N/A a->number_length == number_length &&
550N/A binaryEqual (a->number, number, number_length))
550N/A {
550N/A return 1;
550N/A }
550N/A }
550N/A return 0;
550N/A}
550N/A
1233N/Astatic void
1233N/AsaveAddr (int family,
1233N/A unsigned short address_length, const char *address,
1233N/A unsigned short number_length, const char *number)
550N/A{
550N/A struct addrList *new;
550N/A
550N/A if (checkAddr (family, address_length, address, number_length, number))
550N/A return;
550N/A new = (struct addrList *) malloc (sizeof (struct addrList));
550N/A if (!new) {
550N/A perror ("saveAddr");
550N/A return;
550N/A }
550N/A if ((new->address_length = address_length) > 0) {
550N/A new->address = malloc (address_length);
550N/A if (!new->address) {
550N/A perror ("saveAddr");
550N/A free ((char *) new);
550N/A return;
550N/A }
550N/A bcopy (address, new->address, (int) address_length);
550N/A } else
550N/A new->address = 0;
550N/A if ((new->number_length = number_length) > 0) {
550N/A new->number = malloc (number_length);
550N/A if (!new->number) {
550N/A perror ("saveAddr");
550N/A free (new->address);
550N/A free ((char *) new);
550N/A return;
550N/A }
550N/A bcopy (number, new->number, (int) number_length);
550N/A } else
550N/A new->number = 0;
550N/A new->family = family;
550N/A new->next = addrs;
550N/A addrs = new;
550N/A}
550N/A
1233N/Astatic void
1233N/AwriteLocalAuth (
1233N/A FILE *file,
1233N/A Xauth *auth,
1233N/A char *name)
550N/A{
550N/A int fd;
550N/A
550N/A setAuthNumber (auth, name);
550N/A#ifdef TCPCONN
550N/A#ifdef IPv6
550N/A fd = socket (AF_INET6, SOCK_STREAM, 0);
550N/A#else
550N/A fd = socket (AF_INET, SOCK_STREAM, 0);
550N/A#endif
550N/A DefineSelf (fd, file, auth);
550N/A close (fd);
550N/A#endif
550N/A#ifdef NOTDEF /* DNETCONN */
550N/A fd = socket (AF_DECnet, SOCK_STREAM, 0);
550N/A DefineSelf (fd, file, auth);
550N/A close (fd);
550N/A#endif
550N/A
550N/A DefineLocal (file, auth);
550N/A}
550N/A
550N/A
1233N/Astatic void
1233N/AwriteAddr (
1233N/A int family,
1233N/A int addr_length,
1233N/A char *addr,
1233N/A FILE *file,
1233N/A Xauth *auth)
550N/A{
550N/A
550N/A auth->family = (unsigned short) family;
550N/A auth->address_length = addr_length;
550N/A auth->address = addr;
550N/A writeAuth (file, auth);
550N/A}
550N/A
550N/A
550N/A#if defined(SYSV) && defined(TCPCONN)
1233N/Astatic int
1233N/Aifioctl(
1233N/A int s,
1233N/A int cmd,
1233N/A char *arg)
550N/A{
550N/A struct strioctl ioc;
550N/A int ret;
550N/A
550N/A bzero((char *) &ioc, sizeof(ioc));
550N/A ioc.ic_cmd = cmd;
550N/A ioc.ic_timout = 0;
550N/A if (cmd == SIOCGIFCONF) {
550N/A/* ioc.ic_len = ((struct ifconf *) arg)->ifc_len; */
550N/A/* For jup_alpha3, it wants a smaller size in the length field, uncomment above
550N/A line and delete the next line once that is fixed. Should not give EINVAL */
550N/A ioc.ic_len = 1024;
550N/A ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
550N/A } else {
550N/A ioc.ic_len = sizeof(struct ifreq); ioc.ic_dp = arg;
550N/A }
550N/A ret = ioctl(s, I_STR, (char *) &ioc);
550N/A if (ret != -1 && cmd == SIOCGIFCONF)
550N/A ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
550N/A return(ret);
550N/A}
550N/A#endif /* SYSV && TCPCONN */
550N/A
550N/A
1233N/Astatic void
1233N/ADefineSelf (
1233N/A int fd,
1233N/A FILE *file,
1233N/A Xauth *auth)
550N/A{
550N/A char buf[2048];
550N/A void * bufptr = buf;
550N/A register int n;
550N/A int len;
550N/A char *addr;
550N/A int family;
550N/A#ifdef SIOCGLIFCONF
550N/A struct lifconf ifc;
550N/A register struct lifreq *ifr;
550N/A#ifdef SIOCGLIFNUM
550N/A struct lifnum ifn;
550N/A#endif
550N/A#else
550N/A register struct ifreq *ifr;
550N/A struct ifconf ifc;
550N/A#endif
550N/A
550N/A len = sizeof(buf);
550N/A
550N/A#if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF)
550N/A ifn.lifn_family = AF_UNSPEC;
550N/A ifn.lifn_flags = 0;
550N/A if (ioctl (fd, (int) SIOCGLIFNUM, (char *) &ifn) < 0)
550N/A perror ("Getting interface count");
550N/A if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
550N/A len = ifn.lifn_count * sizeof(struct lifreq);
550N/A bufptr = malloc(len);
550N/A }
550N/A#endif
550N/A
550N/A#ifdef SIOCGLIFCONF
550N/A ifc.lifc_family = AF_UNSPEC;
550N/A ifc.lifc_flags = 0;
550N/A ifc.lifc_len = len;
550N/A ifc.lifc_buf = bufptr;
550N/A if (ioctl (fd, (int) SIOCGLIFCONF, (char *) &ifc) < 0)
550N/A return;
550N/A for (ifr = ifc.lifc_req, n = ifc.lifc_len / sizeof (struct lifreq);
550N/A --n >= 0; ifr++)
550N/A {
550N/A len = sizeof(ifr->lifr_addr);
550N/A {
550N/A family = ConvertAddr ((struct sockaddr *) &ifr->lifr_addr, &len,
550N/A &addr);
550N/A#else
550N/A ifc.ifc_len = len;
550N/A ifc.ifc_buf = buf;
550N/A#if defined(SYSV) && defined(TCPCONN)
550N/A ifioctl (fd, SIOCGIFCONF, (char *) &ifc);
550N/A#else
550N/A ioctl (fd, SIOCGIFCONF, (char *) &ifc);
550N/A#endif /* SYSV && TCPCONN */
550N/A
550N/A for (ifr = ifc.ifc_req, n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0;
550N/A ifr++)
550N/A {
550N/A#ifdef NOTDEF /* DNETCONN */
550N/A /*
550N/A * this is ugly but SIOCGIFCONF returns decnet addresses in
550N/A * a different form from other decnet calls
550N/A */
550N/A if (ifr->ifr_addr.sa_family == AF_DECnet) {
550N/A len = sizeof (struct dn_naddr);
550N/A addr = (char *)ifr->ifr_addr.sa_data;
550N/A family = FamilyDECnet;
550N/A } else
550N/A#endif
550N/A {
550N/A family = ConvertAddr (&ifr->ifr_addr, &len, &addr);
550N/A#endif
550N/A if (family <= 0)
550N/A continue;
550N/A
550N/A /*
550N/A * If we get back a 0.0.0.0 IP address, ignore this entry. This
550N/A * typically happens when a machine is in a standalone mode.
550N/A */
550N/A if(len == 4 && addr[0] == 0 && addr[1] == 0 &&
550N/A addr[2] == 0 && addr[3] == 0)
550N/A continue;
550N/A
550N/A#ifdef IPv6
550N/A if(family == AF_INET6) {
550N/A if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr)))
550N/A continue;
550N/A else
550N/A family = FamilyInternet6;
550N/A } else
550N/A#endif
550N/A family = FamilyInternet;
550N/A }
550N/A
550N/A writeAddr (family, len, addr, file, auth);
550N/A }
550N/A}
550N/A
1233N/Astatic void
1233N/ADefineLocal (
1233N/A FILE *file,
1233N/A Xauth *auth)
550N/A{
550N/A char displayname[100];
550N/A
550N/A /* stolen from xinit.c */
550N/A#ifdef hpux
550N/A /* Why not use gethostname()? Well, at least on my system, I've had to
550N/A * make an ugly kernel patch to get a name longer than 8 characters, and
550N/A * uname() lets me access to the whole string (it smashes release, you
550N/A * see), whereas gethostname() kindly truncates it for me.
550N/A */
550N/A {
550N/A struct utsname name;
550N/A
550N/A uname(&name);
550N/A strcpy(displayname, name.nodename);
550N/A }
550N/A#else
550N/A gethostname(displayname, sizeof(displayname));
550N/A#endif
550N/A writeAddr (FamilyLocal, strlen (displayname), displayname, file, auth);
550N/A}
550N/A
550N/A/* code stolen from server/os/4.2bsd/access.c */
550N/A
550N/Astatic int
1233N/AConvertAddr (
1233N/A register struct sockaddr *saddr,
1233N/A int *len,
1233N/A char **addr)
550N/A{
550N/A if (len == 0)
550N/A return (0);
550N/A switch (saddr->sa_family)
550N/A {
550N/A case AF_UNSPEC:
550N/A#ifndef hpux
550N/A case AF_UNIX:
550N/A#endif
550N/A return (0);
550N/A#ifdef TCPCONN
550N/A case AF_INET:
550N/A *len = sizeof (struct in_addr);
550N/A *addr = (char *) &(((struct sockaddr_in *) saddr)->sin_addr);
550N/A return (AF_INET);
550N/A#ifdef IPv6
550N/A case AF_INET6:
550N/A *len = sizeof (struct in6_addr);
550N/A *addr = (char *) &(((struct sockaddr_in6 *) saddr)->sin6_addr);
550N/A return (AF_INET6);
550N/A#endif
550N/A#endif
550N/A
550N/A#ifdef NOTDEF /* DNETCONN */
550N/A case AF_DECnet:
550N/A *len = sizeof (struct dn_naddr);
550N/A *addr = (char *) &(((struct sockaddr_dn *) saddr)->sdn_add);
550N/A return (AF_DECnet);
550N/A#endif
550N/A default:
550N/A break;
550N/A }
550N/A return (-1);
550N/A}
550N/A
1233N/Astatic void
1233N/AsetAuthNumber (
1233N/A Xauth *auth,
1233N/A char *name)
550N/A{
550N/A char *colon;
550N/A char *dot, *number;
550N/A
550N/A colon = rindex (name, ':');
550N/A if (colon) {
550N/A ++colon;
1233N/A if ((dot = index (colon, '.')))
550N/A auth->number_length = dot - colon;
550N/A else
550N/A auth->number_length = strlen (colon);
550N/A number = malloc (auth->number_length + 1);
550N/A if (number) {
550N/A strncpy (number, colon, auth->number_length);
550N/A number[auth->number_length] = '\0';
550N/A } else {
550N/A perror ("setAuthNumber");
550N/A auth->number_length = 0;
550N/A }
550N/A auth->number = number;
550N/A }
550N/A}
550N/A
1233N/Astatic int
1233N/AopenFiles (char *name, char *new_name, FILE **oldp, FILE **newp)
550N/A{
550N/A int mask;
550N/A
550N/A strcpy (new_name, name);
550N/A strcat (new_name, "-n");
550N/A mask = umask (0077);
550N/A (void) unlink (new_name);
550N/A *newp = fopen (new_name, "w");
550N/A (void) umask (mask);
550N/A if (!*newp) {
550N/A return 0;
550N/A }
550N/A *oldp = fopen (name, "r");
550N/A
550N/A return 1;
550N/A}
550N/A
1233N/Astatic void
1233N/AwriteAuth (
1233N/A FILE *file,
1233N/A Xauth *auth)
550N/A{
550N/A saveAddr (auth->family, auth->address_length, auth->address,
550N/A auth->number_length, auth->number);
550N/A if (!XauWriteAuth (file, auth)) {
550N/A fprintf(stderr,"mkcookie: Could not write authorization info. for user. exiting\n");
550N/A exit(-1);
550N/A }
550N/A}
1233N/A
1233N/Astatic void
1233N/AdoneAddrs (void)
550N/A{
550N/A struct addrList *a, *n;
550N/A for (a = addrs; a; a = n) {
550N/A n = a->next;
550N/A if (a->address)
550N/A free (a->address);
550N/A if (a->number)
550N/A free (a->number);
550N/A free ((char *) a);
550N/A }
550N/A}
550N/A
1233N/Astatic void
1233N/AInitAuth (
1233N/A unsigned short name_len,
1233N/A const char *name)
550N/A{
550N/A if (strcmp(name,"SUN-DES-1") != 0) {
550N/A if (name_len > 256)
550N/A name_len = 256;
550N/A }
550N/A auth_name_len = name_len;
550N/A bcopy (name, auth_name, name_len);
550N/A}
550N/A
1233N/Astatic Xauth *
1233N/AGetAuth (
1233N/A int namelen,
1233N/A const char *name)
550N/A{
550N/A Xauth *new;
550N/A int uid = getuid();
550N/A char netname[MAXNETNAMELEN];
550N/A new = (Xauth *) malloc (sizeof (Xauth));
550N/A
550N/A if (!new)
550N/A return (Xauth *) 0;
550N/A new->family = FamilyWild;
550N/A new->address_length = 0;
550N/A new->address = 0;
550N/A new->number_length = 0;
550N/A new->number = 0;
550N/A
550N/A if (strncmp(name,"MIT-",4) == 0)
550N/A new->data = (char *) malloc (AUTH_DATA_LEN);
550N/A else
550N/A new->data = (char *) malloc (MAXNETNAMELEN);
550N/A if (!new->data)
550N/A {
550N/A free ((char *) new);
550N/A return (Xauth *) 0;
550N/A }
550N/A new->name = (char *) malloc (namelen);
550N/A if (!new->name)
550N/A {
550N/A free ((char *) new->data);
550N/A free ((char *) new);
550N/A return (Xauth *) 0;
550N/A }
550N/A bcopy (name, new->name, namelen);
550N/A new->name_length = namelen;
550N/A if (strncmp(name,"MIT-",4) == 0) {
550N/A GenerateCryptoKey (new->data, AUTH_DATA_LEN);
550N/A new->data_length = AUTH_DATA_LEN;
550N/A } else {
550N/A if (!user2netname(netname, uid, 0))
550N/A perror("user2netname");
550N/A new->data_length = strlen(netname);
550N/A bcopy(netname, new->data, new->data_length);
550N/A }
550N/A return new;
550N/A}
550N/A
1233N/Astatic void
1233N/AGenerateCryptoKey (
1233N/A char *auth,
1233N/A int len)
550N/A{
550N/A long data[2];
550N/A int seed;
550N/A int value;
550N/A int i, t;
1233N/A const char *ran_file = "/dev/random";
550N/A int fd;
550N/A
550N/A if ((fd = open(ran_file, O_RDONLY)) == -1)
550N/A {
550N/A struct timeval now;
550N/A struct timezone zone;
550N/A gettimeofday (&now, &zone);
550N/A data[0] = now.tv_sec;
550N/A data[1] = now.tv_usec;
550N/A
550N/A seed = (data[0]) + (data[1] << 16);
550N/A srand (seed);
550N/A for (i = 0; i < (len - 1); i++)
550N/A {
550N/A value = rand ();
550N/A auth[i] = value & 0xff;
550N/A }
550N/A } else {
550N/A for (i = 0; i < (len - 1); i++)
550N/A {
550N/A read(fd, &t, sizeof(t));
550N/A auth[i] = (
550N/A ( (t & 0xff000000) >> 24) ^
550N/A ( (t & 0xff0000) >> 16) ^
550N/A ( (t & 0xff00) >> 8) ^
550N/A ( (t & 0xff) )
550N/A ) & 0xff;
550N/A }
550N/A close(fd);
550N/A }
550N/A auth[len-1] = '\0';
550N/A}
550N/A
1233N/Astatic int
1233N/ASaveServerAuthorization (
1233N/A char *authFile,
1233N/A Xauth *auth)
550N/A{
550N/A FILE *auth_file;
550N/A int mask;
550N/A int ret;
550N/A
550N/A mask = umask (0077);
550N/A (void) unlink (authFile);
550N/A auth_file = fopen (authFile, "w");
550N/A umask (mask);
550N/A if (!auth_file) {
550N/A ret = FALSE;
550N/A }
550N/A else
550N/A {
550N/A if (!XauWriteAuth (auth_file, auth) || fflush (auth_file) == EOF)
550N/A {
550N/A ret = FALSE;
550N/A }
550N/A else
550N/A ret = TRUE;
550N/A fclose (auth_file);
550N/A }
550N/A chmod(authFile, S_IREAD);
550N/A return ret;
550N/A}
550N/A
550N/A#define NUM_AUTHORIZATION (sizeof (AuthProtocols) / sizeof (AuthProtocols[0]))
550N/A
550N/Astatic struct AuthProtocol *
1233N/AfindProtocol (
1233N/A int name_length,
1233N/A const char *name)
550N/A{
550N/A int i;
550N/A
550N/A for (i = 0; i < NUM_AUTHORIZATION; i++)
550N/A if (AuthProtocols[i].name_length == name_length &&
550N/A bcmp (AuthProtocols[i].name, name, name_length) == 0)
550N/A {
550N/A return &AuthProtocols[i];
550N/A }
550N/A return (struct AuthProtocol *) 0;
550N/A}
550N/A
1233N/Astatic Xauth *
1233N/AGenerateAuthorization (
1233N/A const char *name,
1233N/A int name_length)
550N/A{
550N/A struct AuthProtocol *a;
550N/A Xauth *auth = 0;
550N/A
550N/A a = findProtocol (name_length, name);
550N/A if (a)
550N/A {
550N/A if (!a->inited)
550N/A {
550N/A (*a->InitAuth) (name_length, name);
550N/A a->inited = TRUE;
550N/A }
550N/A auth = (*a->GetAuth) (name_length, name);
550N/A }
550N/A return auth;
550N/A}
550N/A
1233N/Astatic void
1233N/ASetLocalAuthorization (
1233N/A struct display *d)
550N/A{
550N/A Xauth *auth;
550N/A int nl = d->authNameLen;
550N/A
550N/A if (d->authorization)
550N/A {
550N/A XauDisposeAuth (d->authorization);
550N/A d->authorization = (Xauth *) NULL;
550N/A }
550N/A if (d->authName && !d->authNameLen)
550N/A d->authNameLen = strlen (d->authName);
550N/A auth = GenerateAuthorization ( d->authName, nl);
550N/A if (!auth)
550N/A return;
550N/A
550N/A /* Change to real user id, before writing any files */
550N/A
550N/A setuid(getuid());
550N/A if (SaveServerAuthorization (d->authFile, auth))
550N/A d->authorization = auth;
550N/A else {
550N/A XauDisposeAuth (auth);
550N/A fprintf(stderr,"mkcookie: Could not write server authorization file. exiting\n");
550N/A exit(-1);
550N/A }
550N/A}
550N/A
1233N/Astatic void
1233N/ASetUserAuthorization (
1233N/A struct display *d,
1233N/A struct verify_info *verify)
550N/A{
550N/A FILE *old, *new;
550N/A char home_name[1024], backup_name[1024], new_name[1024];
550N/A char *name;
550N/A char *home;
550N/A char *envname = 0;
550N/A int lockStatus;
550N/A Xauth *entry, *auth;
550N/A int setenv;
550N/A struct stat statb;
550N/A
1233N/A if ((auth = d->authorization)) {
550N/A home = getenv("HOME");
550N/A lockStatus = LOCK_ERROR;
550N/A if (home) {
550N/A snprintf (home_name, 1024, "%s/.Xauthority", home);
550N/A lockStatus = XauLockAuth (home_name, 1, 2, 10);
550N/A if (lockStatus == LOCK_SUCCESS) {
550N/A if (openFiles (home_name, new_name, &old, &new)) {
550N/A name = home_name;
550N/A setenv = 0;
550N/A } else {
550N/A XauUnlockAuth (home_name);
550N/A lockStatus = LOCK_ERROR;
550N/A }
550N/A }
550N/A }
550N/A if (lockStatus != LOCK_SUCCESS) {
550N/A sprintf (backup_name, "%s/.XauthXXXXXX", d->userAuthDir);
550N/A mktemp (backup_name);
550N/A lockStatus = XauLockAuth (backup_name, 1, 2, 10);
550N/A
550N/A if (lockStatus == LOCK_SUCCESS) {
550N/A if (openFiles (backup_name, new_name, &old, &new)) {
550N/A name = backup_name;
550N/A setenv = 1;
550N/A } else {
550N/A XauUnlockAuth (backup_name);
550N/A lockStatus = LOCK_ERROR;
550N/A }
550N/A }
550N/A }
550N/A if (lockStatus != LOCK_SUCCESS) {
550N/A return;
550N/A }
550N/A addrs = 0;
550N/A if (d->displayType.location == Local)
550N/A writeLocalAuth (new, auth, d->name);
550N/A
550N/A if (old) {
550N/A if (fstat (fileno (old), &statb) != -1)
550N/A chmod (new_name, (int) (statb.st_mode & 0777));
1233N/A while ((entry = XauReadAuth (old))) {
550N/A if (!checkAddr (entry->family,
550N/A entry->address_length, entry->address,
550N/A entry->number_length, entry->number))
550N/A {
550N/A writeAuth (new, entry);
550N/A }
550N/A XauDisposeAuth (entry);
550N/A }
550N/A fclose (old);
550N/A }
550N/A doneAddrs ();
550N/A fclose (new);
550N/A unlink (name);
550N/A
550N/A envname = name;
550N/A if (link (new_name, name) == -1) {
550N/A setenv = 1;
550N/A envname = new_name;
550N/A } else {
550N/A unlink (new_name);
550N/A }
550N/A if (setenv) {
550N/A verify->userEnviron = setEnv (verify->userEnviron,
550N/A "XAUTHORITY", envname);
550N/A verify->systemEnviron = setEnv (verify->systemEnviron,
550N/A "XAUTHORITY", envname);
550N/A }
550N/A XauUnlockAuth (name);
550N/A if (envname)
550N/A chown (envname, verify->uid, verify->gid);
550N/A }
550N/A
550N/A}
550N/A
1233N/Astatic void
1233N/Ausage(const char *str)
550N/A{
550N/A fprintf(stderr,"usage: %s Server_auth_file [-auth protocol]\n",str);
550N/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{
550N/A struct display d;
550N/A struct verify_info verify;
550N/A char *au_name;
550N/A
550N/A
550N/A if (argc < 2) {
550N/A usage(argv[0]);
550N/A fprintf(stderr,"WARNING: This program will overwrite existing files.\n");
550N/A fprintf(stderr,"This may cause your X server to not accept any\n");
550N/A fprintf(stderr,"new client connections.\n");
550N/A exit(-1);
550N/A }
550N/A
550N/A au_name = NULL;
550N/A d.authFile = argv[1];
550N/A
550N/A if ((d.name = rindex(d.authFile,':')) == NULL) {
550N/A fprintf(stderr,"mkcookie: Invalid filename: %s\nFilename should include display\n",
550N/A d.authFile);
550N/A exit(-1);
550N/A }
550N/A d.authorize = TRUE;
550N/A d.authorization = NULL;
550N/A /* 1191081: SIGSEGV when starting openwin - core dumped by mkcookie.
550N/A * becuase d.userAuthDir is not assigned any valid directory where
550N/A * every one will have access to it.
550N/A */
550N/A d.userAuthDir = DEF_USER_AUTH_DIR; /* Backup directory for User Auth file */
550N/A d.authName = "MIT-MAGIC-COOKIE-1";
550N/A
550N/A if (argv[2] && strcmp(argv[2],"-auth") == 0) {
550N/A if (argv[3])
550N/A au_name = argv[3];
550N/A else {
550N/A usage(argv[0]);
550N/A exit(-1);
550N/A }
550N/A } else if (argv[2]) {
550N/A usage(argv[0]);
550N/A exit(-1);
550N/A }
550N/A
550N/A if (au_name) {
550N/A if(strcmp(au_name, "sun-des") == 0)
550N/A d.authName = "SUN-DES-1";
550N/A else if (strncmp(au_name,"magic",5) != 0) {
550N/A usage(argv[0]);
550N/A exit(-1);
550N/A }
550N/A }
550N/A d.authNameLen = strlen(d.authName);
550N/A d.peer = 0;
550N/A d.peerlen = 0;
550N/A d.displayType.location = Local;
550N/A
550N/A verify.uid = getuid();
550N/A verify.gid = getgid();
550N/A verify.userEnviron = NULL;
550N/A verify.systemEnviron = NULL;
550N/A
550N/A SetLocalAuthorization(&d);
550N/A SetUserAuthorization(&d, &verify);
550N/A exit(0);
550N/A}