320 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			320 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 | 
						|
Copyright 1988, 1998  The Open Group
 | 
						|
 | 
						|
Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
documentation for any purpose is hereby granted without fee, provided that
 | 
						|
the above copyright notice appear in all copies and that both that
 | 
						|
copyright notice and this permission notice appear in supporting
 | 
						|
documentation.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included
 | 
						|
in all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 | 
						|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 | 
						|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 | 
						|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 | 
						|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
						|
OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall
 | 
						|
not be used in advertising or otherwise to promote the sale, use or
 | 
						|
other dealings in this Software without prior written authorization
 | 
						|
from The Open Group.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
/*
 | 
						|
 * authorization hooks for the server
 | 
						|
 * Author:  Keith Packard, MIT X Consortium
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include   <X11/X.h>
 | 
						|
#include   <X11/Xauth.h>
 | 
						|
#include   "misc.h"
 | 
						|
#include   "osdep.h"
 | 
						|
#include   "dixstruct.h"
 | 
						|
#include   <sys/types.h>
 | 
						|
#include   <sys/stat.h>
 | 
						|
#ifdef WIN32
 | 
						|
#include    <X11/Xw32defs.h>
 | 
						|
#endif
 | 
						|
#ifdef HAVE_LIBBSD
 | 
						|
#include   <bsd/stdlib.h>       /* for arc4random_buf() */
 | 
						|
#endif
 | 
						|
 | 
						|
struct protocol {
 | 
						|
    unsigned short name_length;
 | 
						|
    const char *name;
 | 
						|
    AuthAddCFunc Add;           /* new authorization data */
 | 
						|
    AuthCheckFunc Check;        /* verify client authorization data */
 | 
						|
    AuthRstCFunc Reset;         /* delete all authorization data entries */
 | 
						|
    AuthFromIDFunc FromID;      /* convert ID to cookie */
 | 
						|
    AuthRemCFunc Remove;        /* remove a specific cookie */
 | 
						|
#ifdef XCSECURITY
 | 
						|
    AuthGenCFunc Generate;
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
static struct protocol protocols[] = {
 | 
						|
    {(unsigned short) 18, "MIT-MAGIC-COOKIE-1",
 | 
						|
     MitAddCookie, MitCheckCookie, MitResetCookie,
 | 
						|
     MitFromID, MitRemoveCookie,
 | 
						|
#ifdef XCSECURITY
 | 
						|
     MitGenerateCookie
 | 
						|
#endif
 | 
						|
     },
 | 
						|
#ifdef HASXDMAUTH
 | 
						|
    {(unsigned short) 19, "XDM-AUTHORIZATION-1",
 | 
						|
     XdmAddCookie, XdmCheckCookie, XdmResetCookie,
 | 
						|
     XdmFromID, XdmRemoveCookie,
 | 
						|
#ifdef XCSECURITY
 | 
						|
     NULL
 | 
						|
#endif
 | 
						|
     },
 | 
						|
#endif
 | 
						|
#ifdef SECURE_RPC
 | 
						|
    {(unsigned short) 9, "SUN-DES-1",
 | 
						|
     SecureRPCAdd, SecureRPCCheck, SecureRPCReset,
 | 
						|
     SecureRPCFromID, SecureRPCRemove,
 | 
						|
#ifdef XCSECURITY
 | 
						|
     NULL
 | 
						|
#endif
 | 
						|
     },
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
#define NUM_AUTHORIZATION  (sizeof (protocols) /\
 | 
						|
			     sizeof (struct protocol))
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize all classes of authorization by reading the
 | 
						|
 * specified authorization file
 | 
						|
 */
 | 
						|
 | 
						|
static const char *authorization_file = NULL;
 | 
						|
 | 
						|
static Bool ShouldLoadAuth = TRUE;
 | 
						|
 | 
						|
void
 | 
						|
InitAuthorization(const char *file_name)
 | 
						|
{
 | 
						|
    authorization_file = file_name;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
LoadAuthorization(void)
 | 
						|
{
 | 
						|
    FILE *f;
 | 
						|
    Xauth *auth;
 | 
						|
    int i;
 | 
						|
    int count = 0;
 | 
						|
 | 
						|
    ShouldLoadAuth = FALSE;
 | 
						|
    if (!authorization_file)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    f = Fopen(authorization_file, "r");
 | 
						|
    if (!f)
 | 
						|
        return -1;
 | 
						|
 | 
						|
    while ((auth = XauReadAuth(f)) != 0) {
 | 
						|
        for (i = 0; i < NUM_AUTHORIZATION; i++) {
 | 
						|
            if (protocols[i].name_length == auth->name_length &&
 | 
						|
                memcmp(protocols[i].name, auth->name,
 | 
						|
                       (int) auth->name_length) == 0 && protocols[i].Add) {
 | 
						|
                ++count;
 | 
						|
                (*protocols[i].Add) (auth->data_length, auth->data,
 | 
						|
                                     FakeClientID(0));
 | 
						|
            }
 | 
						|
        }
 | 
						|
        XauDisposeAuth(auth);
 | 
						|
    }
 | 
						|
 | 
						|
    Fclose(f);
 | 
						|
    return count;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef XDMCP
 | 
						|
/*
 | 
						|
 * XdmcpInit calls this function to discover all authorization
 | 
						|
 * schemes supported by the display
 | 
						|
 */
 | 
						|
void
 | 
						|
RegisterAuthorizations(void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < NUM_AUTHORIZATION; i++)
 | 
						|
        XdmcpRegisterAuthorization(protocols[i].name,
 | 
						|
                                   (int) protocols[i].name_length);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
XID
 | 
						|
CheckAuthorization(unsigned int name_length,
 | 
						|
                   const char *name,
 | 
						|
                   unsigned int data_length,
 | 
						|
                   const char *data, ClientPtr client, const char **reason)
 | 
						|
{                               /* failure message.  NULL for default msg */
 | 
						|
    int i;
 | 
						|
    struct stat buf;
 | 
						|
    static time_t lastmod = 0;
 | 
						|
    static Bool loaded = FALSE;
 | 
						|
 | 
						|
    if (!authorization_file || stat(authorization_file, &buf)) {
 | 
						|
        if (lastmod != 0) {
 | 
						|
            lastmod = 0;
 | 
						|
            ShouldLoadAuth = TRUE;      /* stat lost, so force reload */
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (buf.st_mtime > lastmod) {
 | 
						|
        lastmod = buf.st_mtime;
 | 
						|
        ShouldLoadAuth = TRUE;
 | 
						|
    }
 | 
						|
    if (ShouldLoadAuth) {
 | 
						|
        int loadauth = LoadAuthorization();
 | 
						|
 | 
						|
        /*
 | 
						|
         * If the authorization file has at least one entry for this server,
 | 
						|
         * disable local access. (loadauth > 0)
 | 
						|
         *
 | 
						|
         * If there are zero entries (either initially or when the
 | 
						|
         * authorization file is later reloaded), or if a valid
 | 
						|
         * authorization file was never loaded, enable local access.
 | 
						|
         * (loadauth == 0 || !loaded)
 | 
						|
         *
 | 
						|
         * If the authorization file was loaded initially (with valid
 | 
						|
         * entries for this server), and reloading it later fails, don't
 | 
						|
         * change anything. (loadauth == -1 && loaded)
 | 
						|
         */
 | 
						|
 | 
						|
        if (loadauth > 0) {
 | 
						|
            DisableLocalAccess(); /* got at least one */
 | 
						|
            loaded = TRUE;
 | 
						|
        }
 | 
						|
        else if (loadauth == 0 || !loaded)
 | 
						|
            EnableLocalAccess();
 | 
						|
    }
 | 
						|
    if (name_length) {
 | 
						|
        for (i = 0; i < NUM_AUTHORIZATION; i++) {
 | 
						|
            if (protocols[i].name_length == name_length &&
 | 
						|
                memcmp(protocols[i].name, name, (int) name_length) == 0) {
 | 
						|
                return (*protocols[i].Check) (data_length, data, client,
 | 
						|
                                              reason);
 | 
						|
            }
 | 
						|
            *reason = "Protocol not supported by server\n";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
        *reason = "No protocol specified\n";
 | 
						|
    return (XID) ~0L;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ResetAuthorization(void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < NUM_AUTHORIZATION; i++)
 | 
						|
        if (protocols[i].Reset)
 | 
						|
            (*protocols[i].Reset) ();
 | 
						|
    ShouldLoadAuth = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
AuthorizationFromID(XID id,
 | 
						|
                    unsigned short *name_lenp,
 | 
						|
                    const char **namep, unsigned short *data_lenp, char **datap)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < NUM_AUTHORIZATION; i++) {
 | 
						|
        if (protocols[i].FromID &&
 | 
						|
            (*protocols[i].FromID) (id, data_lenp, datap)) {
 | 
						|
            *name_lenp = protocols[i].name_length;
 | 
						|
            *namep = protocols[i].name;
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
RemoveAuthorization(unsigned short name_length,
 | 
						|
                    const char *name,
 | 
						|
                    unsigned short data_length, const char *data)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < NUM_AUTHORIZATION; i++) {
 | 
						|
        if (protocols[i].name_length == name_length &&
 | 
						|
            memcmp(protocols[i].name, name, (int) name_length) == 0 &&
 | 
						|
            protocols[i].Remove) {
 | 
						|
            return (*protocols[i].Remove) (data_length, data);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
AddAuthorization(unsigned name_length, const char *name,
 | 
						|
                 unsigned data_length, char *data)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < NUM_AUTHORIZATION; i++) {
 | 
						|
        if (protocols[i].name_length == name_length &&
 | 
						|
            memcmp(protocols[i].name, name, (int) name_length) == 0 &&
 | 
						|
            protocols[i].Add) {
 | 
						|
            return (*protocols[i].Add) (data_length, data, FakeClientID(0));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef XCSECURITY
 | 
						|
 | 
						|
XID
 | 
						|
GenerateAuthorization(unsigned name_length,
 | 
						|
                      const char *name,
 | 
						|
                      unsigned data_length,
 | 
						|
                      const char *data,
 | 
						|
                      unsigned *data_length_return, char **data_return)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < NUM_AUTHORIZATION; i++) {
 | 
						|
        if (protocols[i].name_length == name_length &&
 | 
						|
            memcmp(protocols[i].name, name, (int) name_length) == 0 &&
 | 
						|
            protocols[i].Generate) {
 | 
						|
            return (*protocols[i].Generate) (data_length, data,
 | 
						|
                                             FakeClientID(0),
 | 
						|
                                             data_length_return, data_return);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
GenerateRandomData(int len, char *buf)
 | 
						|
{
 | 
						|
#ifdef HAVE_ARC4RANDOM_BUF
 | 
						|
    arc4random_buf(buf, len);
 | 
						|
#else
 | 
						|
    int fd;
 | 
						|
 | 
						|
    fd = open("/dev/urandom", O_RDONLY);
 | 
						|
    read(fd, buf, len);
 | 
						|
    close(fd);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#endif                          /* XCSECURITY */
 |