/* This just gets a cookie of MIT-MAGIC-COOKIE-1 type */ char * mdmcomm_get_a_cookie (gboolean binary) { FILE *fp; char *number; char *cookie = NULL; Xauth *xau; VE_IGNORE_EINTR (fp = fopen (XauFileName (), "r")); if (fp == NULL) { return NULL; } number = get_dispnum (); cookie = NULL; while ((xau = XauReadAuth (fp)) != NULL) { /* Just find the FIRST magic cookie, that's what mdm uses */ if (xau->number_length != strlen (number) || strncmp (xau->number, number, xau->number_length) != 0 || /* mdm sends MIT-MAGIC-COOKIE-1 cookies of length 16, * so just do those */ xau->data_length != 16 || xau->name_length != strlen ("MIT-MAGIC-COOKIE-1") || strncmp (xau->name, "MIT-MAGIC-COOKIE-1", xau->name_length) != 0) { XauDisposeAuth (xau); continue; } if (binary) { cookie = g_new0 (char, 16); memcpy (cookie, xau->data, 16); } else { int i; GString *str; str = g_string_new (NULL); for (i = 0; i < xau->data_length; i++) { g_string_append_printf (str, "%02x", (guint)(guchar)xau->data[i]); } cookie = g_string_free (str, FALSE); } XauDisposeAuth (xau); break; }
void DM::GDMAuthenticate() { FILE *fp; const char *dpy, *dnum, *dne; int dnl; Xauth *xau; dpy = DisplayString(QPaintDevice::x11AppDisplay()); if(!dpy) { dpy = ::getenv("DISPLAY"); if(!dpy) return; } dnum = strchr(dpy, ':') + 1; dne = strchr(dpy, '.'); dnl = dne ? dne - dnum : strlen(dnum); /* XXX should do locking */ if(!(fp = fopen(XauFileName(), "r"))) return; while((xau = XauReadAuth(fp))) { if(xau->family == FamilyLocal && xau->number_length == dnl && !memcmp(xau->number, dnum, dnl) && xau->data_length == 16 && xau->name_length == 18 && !memcmp(xau->name, "MIT-MAGIC-COOKIE-1", 18)) { QString cmd("AUTH_LOCAL "); for(int i = 0; i < 16; i++) cmd += QString::number((uchar)xau->data[i], 16).rightJustify(2, '0'); cmd += "\n"; if(exec(cmd.latin1())) { XauDisposeAuth(xau); break; } } XauDisposeAuth(xau); } fclose(fp); }
static Xauth* find_auth_cookie (FILE *f) { Xauth *ret = NULL; char local_hostname[MaxHostNameLen]; char *display_str = getenv("DISPLAY"); char d[MaxHostNameLen + 4]; char *colon; struct addrinfo *ai; struct addrinfo hints; int disp; int error; if(display_str == NULL) display_str = ":0"; strlcpy(d, display_str, sizeof(d)); display_str = d; colon = strchr (display_str, ':'); if (colon == NULL) disp = 0; else { *colon = '\0'; disp = atoi (colon + 1); } if (strcmp (display_str, "") == 0 || strncmp (display_str, "unix", 4) == 0 || strncmp (display_str, "localhost", 9) == 0) { gethostname (local_hostname, sizeof(local_hostname)); display_str = local_hostname; } memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; error = getaddrinfo (display_str, NULL, &hints, &ai); if (error) ai = NULL; for (; (ret = XauReadAuth (f)) != NULL; XauDisposeAuth(ret)) { if (match_local_auth (ret, ai, display_str, disp) == 0) { if (ai != NULL) freeaddrinfo (ai); return ret; } } if (ai != NULL) freeaddrinfo (ai); return NULL; }
int LoadAuthorization (void) { FILE *f; Xauth *auth; int i; int count = 0; #if !defined(WIN32) && !defined(__UNIXOS2__) char *buf; #endif ShouldLoadAuth = FALSE; if (!authorization_file) return 0; #if !defined(WIN32) && !defined(__UNIXOS2__) buf = xalloc (strlen(authorization_file) + 5); if (!buf) return -1; sprintf (buf, "cat %s", authorization_file); f = Popen (buf, "r"); xfree (buf); #else f = fopen (authorization_file, "r"); #endif 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); } #if !defined(WIN32) && !defined(__UNIXOS2__) if (Pclose (f) != 0) return -1; #else fclose (f); #endif return count; }
static Xauth * read_numeric(FILE *fp) { Xauth *auth; auth = (Xauth *) malloc (sizeof (Xauth)); if (!auth) goto bad; auth->family = 0; auth->address = NULL; auth->address_length = 0; auth->number = NULL; auth->number_length = 0; auth->name = NULL; auth->name_length = 0; auth->data = NULL; auth->data_length = 0; if (!get_short (fp, (unsigned short *) &auth->family)) goto bad; if (!get_short (fp, (unsigned short *) &auth->address_length)) goto bad; if (!get_bytes (fp, (unsigned int) auth->address_length, &auth->address)) goto bad; if (!get_short (fp, (unsigned short *) &auth->number_length)) goto bad; if (!get_bytes (fp, (unsigned int) auth->number_length, &auth->number)) goto bad; if (!get_short (fp, (unsigned short *) &auth->name_length)) goto bad; if (!get_bytes (fp, (unsigned int) auth->name_length, &auth->name)) goto bad; if (!get_short (fp, (unsigned short *) &auth->data_length)) goto bad; if (!get_bytes (fp, (unsigned int) auth->data_length, &auth->data)) goto bad; switch (getinput (fp)) { /* get end of line */ case EOF: case '\n': return auth; } bad: if (auth) XauDisposeAuth (auth); /* won't free null pointers */ return NULL; }
/* ARGSUSED */ static int remove_entry(char *inputfilename, int lineno, Xauth *auth, char *data) { int *nremovedp = (int *) data; AuthList **listp = &xauth_head; AuthList *list; /* * unlink the auth we were asked to */ while ((list = *listp)->auth != auth) listp = &list->next; *listp = list->next; XauDisposeAuth (list->auth); /* free the auth */ free (list); /* free the link */ xauth_modified = True; (*nremovedp)++; return 1; }
static void freeDisplay(struct display *d) { char **x; int i; IfFree(d->name); IfFree(d->class); for (x = d->argv; x && *x; x++) IfFree(*x); IfFree(d->argv); IfFree(d->resources); IfFree(d->xrdb); IfFree(d->setup); IfFree(d->startup); IfFree(d->reset); IfFree(d->session); IfFree(d->userPath); IfFree(d->systemPath); IfFree(d->systemShell); IfFree(d->failsafeClient); IfFree(d->chooser); if (d->authorizations) { for (i = 0; i < d->authNum; i++) XauDisposeAuth(d->authorizations[i]); free(d->authorizations); } IfFree(d->clientAuthFile); if (d->authFile) (void)unlink(d->authFile); IfFree(d->authFile); IfFree(d->userAuthDir); for (x = d->authNames; x && *x; x++) IfFree(*x); IfFree(d->authNames); IfFree(d->authNameLens); #ifdef XDMCP IfFree(d->peer); IfFree(d->from); XdmcpDisposeARRAY8(&d->clientAddr); #endif free(d); }
void RemoveDisplay(struct display *old) { struct display *d, **dp; int i; for(dp = &displays; (d = *dp); dp = &(*dp)->next) { if(d == old) { Debug("Removing display %s\n", d->name); *dp = d->next; IfFree(d->class2); IfFree(d->cfg.data); delStr(d->cfg.dep.name); #ifdef XDMCP IfFree(d->remoteHost); #endif if(d->authorizations) { for(i = 0; i < d->authNum; i++) XauDisposeAuth(d->authorizations[i]); free((char *)d->authorizations); } if(d->authFile) { (void)unlink(d->authFile); free(d->authFile); } IfFree(d->authNameLens); #ifdef XDMCP XdmcpDisposeARRAY8(&d->peer); XdmcpDisposeARRAY8(&d->from); XdmcpDisposeARRAY8(&d->clientAddr); #endif free((char *)d); break; } } }
static int LoadAuthorization(void) { FILE *f; Xauth *auth; int i; int count = 0; ShouldLoadAuth = FALSE; if (!authorization_file) return 0; errno = 0; f = Fopen(authorization_file, "r"); if (!f) { LogMessageVerb(X_ERROR, 0, "Failed to open authorization file \"%s\": %s\n", authorization_file, errno != 0 ? strerror(errno) : "Unknown error"); 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; }
static int merge_entries(AuthList **firstp, AuthList *second, int *nnewp, int *nreplp) { AuthList *a, *b, *first, *tail; int n = 0, nnew = 0, nrepl = 0; if (!second) return 0; if (!*firstp) { /* if nothing to merge into */ *firstp = second; for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ; *nnewp = n; *nreplp = 0; return n; } first = *firstp; /* * find end of first list and stick second list on it */ for (tail = first; tail->next; tail = tail->next) ; tail->next = second; /* * run down list freeing duplicate entries; if an entry is okay, then * bump the tail up to include it, otherwise, cut the entry out of * the chain. */ for (b = second; b; ) { AuthList *next = b->next; /* in case we free it */ a = first; for (;;) { if (match_auth (a->auth, b->auth)) { /* found a duplicate */ AuthList tmp; /* swap it in for old one */ tmp = *a; *a = *b; *b = tmp; a->next = b->next; XauDisposeAuth (b->auth); free ((char *) b); b = NULL; tail->next = next; nrepl++; nnew--; break; } if (a == tail) break; /* if have looked at left side */ a = a->next; } if (b) { /* if we didn't remove it */ tail = b; /* bump end of first list */ } b = next; n++; nnew++; } *nnewp = nnew; *nreplp = nrepl; return n; }
Xauth * XauGetAuthByAddr ( #if NeedWidePrototypes unsigned int family, unsigned int address_length, #else unsigned short family, unsigned short address_length, #endif _Xconst char* address, #if NeedWidePrototypes unsigned int number_length, #else unsigned short number_length, #endif _Xconst char* number, #if NeedWidePrototypes unsigned int name_length, #else unsigned short name_length, #endif _Xconst char* name) { FILE *auth_file; char *auth_name; Xauth *entry; auth_name = XauFileName (); if (!auth_name) return NULL; if (access (auth_name, R_OK) != 0) /* checks REAL id */ return NULL; auth_file = fopen (auth_name, "rb"); if (!auth_file) return NULL; for (;;) { entry = XauReadAuth (auth_file); if (!entry) break; /* * Match when: * either family or entry->family are FamilyWild or * family and entry->family are the same and * address and entry->address are the same * and * either number or entry->number are empty or * number and entry->number are the same * and * either name or entry->name are empty or * name and entry->name are the same */ if ((family == FamilyWild || entry->family == FamilyWild || (entry->family == family && address_length == entry->address_length && binaryEqual (entry->address, address, address_length))) && (number_length == 0 || entry->number_length == 0 || (number_length == entry->number_length && binaryEqual (entry->number, number, number_length))) && (name_length == 0 || entry->name_length == 0 || (entry->name_length == name_length && binaryEqual (entry->name, name, name_length)))) break; XauDisposeAuth (entry); } (void) fclose (auth_file); return entry; }
int startClient( volatile int *pid ) { const char *home, *sessargs, *desksess; char **env, *xma; char **argv, *fname, *str; #ifdef USE_PAM char ** volatile pam_env; # ifndef HAVE_PAM_GETENVLIST char **saved_env; # endif int pretc; #else # ifdef _AIX char *msg; char **theenv; extern char **newenv; /* from libs.a, this is set up by setpenv */ # endif #endif #ifdef HAVE_SETUSERCONTEXT extern char **environ; #endif char *failsafeArgv[2]; char *buf, *buf2; int i; if (strCmp( dmrcuser, curuser )) { if (curdmrc) { free( curdmrc ); curdmrc = 0; } if (dmrcuser) { free( dmrcuser ); dmrcuser = 0; } } #if defined(USE_PAM) || defined(_AIX) if (!(p = getpwnam( curuser ))) { logError( "getpwnam(%s) failed.\n", curuser ); pError: displayStr( V_MSG_ERR, 0 ); return 0; } #endif #ifndef USE_PAM # ifdef _AIX msg = NULL; loginsuccess( curuser, hostname, tty, &msg ); if (msg) { debug( "loginsuccess() - %s\n", msg ); free( (void *)msg ); } # else /* _AIX */ # if defined(KERBEROS) && defined(AFS) if (krbtkfile[0] != '\0') { if (k_hasafs()) { int fail = 0; if (k_setpag() == -1) { logError( "setpag() for %s failed\n", curuser ); fail = 1; } if ((ret = k_afsklog( NULL, NULL )) != KSUCCESS) { logError( "AFS Warning: %s\n", krb_get_err_text( ret ) ); fail = 1; } if (fail) displayMsg( V_MSG_ERR, "Warning: Problems during Kerberos4/AFS setup." ); } } # endif /* KERBEROS && AFS */ # endif /* _AIX */ #endif /* !PAM */ curuid = p->pw_uid; curgid = p->pw_gid; env = baseEnv( curuser ); xma = 0; strApp( &xma, "method=", curtype, (char *)0 ); if (td_setup) strApp( &xma, ",auto", (char *)0 ); if (xma) { env = setEnv( env, "XDM_MANAGED", xma ); free( xma ); } if (td->autoLock && cursource == PWSRC_AUTOLOGIN) env = setEnv( env, "DESKTOP_LOCKED", "true" ); env = setEnv( env, "PATH", curuid ? td->userPath : td->systemPath ); env = setEnv( env, "SHELL", p->pw_shell ); env = setEnv( env, "HOME", p->pw_dir ); #if !defined(USE_PAM) && !defined(_AIX) && defined(KERBEROS) if (krbtkfile[0] != '\0') env = setEnv( env, "KRBTKFILE", krbtkfile ); #endif userEnviron = inheritEnv( env, envvars ); env = systemEnv( curuser ); systemEnviron = setEnv( env, "HOME", p->pw_dir ); debug( "user environment:\n%[|''>'\n's" "system environment:\n%[|''>'\n's" "end of environments\n", userEnviron, systemEnviron ); /* * for user-based authorization schemes, * add the user to the server's allowed "hosts" list. */ for (i = 0; i < td->authNum; i++) { #ifdef SECURE_RPC if (td->authorizations[i]->name_length == 9 && !memcmp( td->authorizations[i]->name, "SUN-DES-1", 9 )) { XHostAddress addr; char netname[MAXNETNAMELEN+1]; char domainname[MAXNETNAMELEN+1]; getdomainname( domainname, sizeof(domainname) ); user2netname( netname, curuid, domainname ); addr.family = FamilyNetname; addr.length = strlen( netname ); addr.address = netname; XAddHost( dpy, &addr ); } #endif #ifdef K5AUTH if (td->authorizations[i]->name_length == 14 && !memcmp( td->authorizations[i]->name, "MIT-KERBEROS-5", 14 )) { /* Update server's auth file with user-specific info. * Don't need to AddHost because X server will do that * automatically when it reads the cache we are about * to point it at. */ XauDisposeAuth( td->authorizations[i] ); td->authorizations[i] = krb5GetAuthFor( 14, "MIT-KERBEROS-5", td->name ); saveServerAuthorizations( td, td->authorizations, td->authNum ); } #endif } if (*dmrcDir) mergeSessionArgs( TRUE ); debug( "now starting the session\n" ); #ifdef USE_PAM # ifdef HAVE_SETUSERCONTEXT if (setusercontext( lc, p, p->pw_uid, LOGIN_SETGROUP )) { logError( "setusercontext(groups) for %s failed: %m\n", curuser ); goto pError; } # else if (!setGid( curuser, curgid )) goto pError; # endif # ifndef HAVE_PAM_GETENVLIST if (!(pam_env = initStrArr( 0 ))) { resetGids(); goto pError; } saved_env = environ; environ = pam_env; # endif removeCreds = 1; /* set it first - i don't trust PAM's rollback */ pretc = pam_setcred( pamh, 0 ); reInitErrorLog(); # ifndef HAVE_PAM_GETENVLIST pam_env = environ; environ = saved_env; # endif # ifdef HAVE_INITGROUPS /* This seems to be a strange place for it, but do it: - after the initial groups are set - after pam_setcred might have set something, even in the error case - before pam_setcred(DELETE_CRED) might need it */ if (!saveGids()) goto pError; # endif if (pretc != PAM_SUCCESS) { logError( "pam_setcred() for %s failed: %s\n", curuser, pam_strerror( pamh, pretc ) ); resetGids(); return 0; } removeSession = 1; /* set it first - same as above */ pretc = pam_open_session( pamh, 0 ); reInitErrorLog(); if (pretc != PAM_SUCCESS) { logError( "pam_open_session() for %s failed: %s\n", curuser, pam_strerror( pamh, pretc ) ); resetGids(); return 0; } /* we don't want sessreg and the startup/reset scripts run with user credentials. unfortunately, we can reset only the gids. */ resetGids(); # define D_LOGIN_SETGROUP LOGIN_SETGROUP #else /* USE_PAM */ # define D_LOGIN_SETGROUP 0 #endif /* USE_PAM */ removeAuth = 1; chownCtrl( &td->ctrl, curuid ); endpwent(); #if !defined(USE_PAM) && defined(USESHADOW) && !defined(_AIX) endspent(); #endif ctltalk.pipe = &ctlpipe; ASPrintf( &buf, "sub-daemon for display %s", td->name ); ASPrintf( &buf2, "client for display %s", td->name ); switch (gFork( &ctlpipe, buf, buf2, 0, 0, mstrtalk.pipe, pid )) { case 0: gCloseOnExec( ctltalk.pipe ); if (Setjmp( ctltalk.errjmp )) exit( 1 ); gCloseOnExec( mstrtalk.pipe ); if (Setjmp( mstrtalk.errjmp )) goto cError; #ifndef NOXDMTITLE setproctitle( "%s'", td->name ); #endif strApp( &prog, " '", (char *)0 ); reInitErrorLog(); setsid(); sessreg( td, getpid(), curuser, curuid ); /* We do this here, as we want to have the session as parent. */ switch (source( systemEnviron, td->startup, td_setup )) { case 0: break; case wcCompose( 0, 0, 127 ): goto cError; default: /* Explicit failure => message already displayed. */ logError( "Startup script returned non-zero exit code\n" ); exit( 1 ); } /* Memory leaks are ok here as we exec() soon. */ #if defined(USE_PAM) || !defined(_AIX) # ifdef USE_PAM /* pass in environment variables set by libpam and modules it called */ # ifdef HAVE_PAM_GETENVLIST pam_env = pam_getenvlist( pamh ); reInitErrorLog(); # endif if (pam_env) for (; *pam_env; pam_env++) userEnviron = putEnv( *pam_env, userEnviron ); # endif # ifdef HAVE_SETLOGIN if (setlogin( curuser ) < 0) { logError( "setlogin for %s failed: %m\n", curuser ); goto cError; } # define D_LOGIN_SETLOGIN LOGIN_SETLOGIN # else # define D_LOGIN_SETLOGIN 0 # endif # if defined(USE_PAM) && defined(HAVE_INITGROUPS) if (!restoreGids()) goto cError; # endif # ifndef HAVE_SETUSERCONTEXT # ifdef USE_PAM if (!setUid( curuser, curuid )) goto cError; # else if (!setUser( curuser, curuid, curgid )) goto cError; # endif # else /* !HAVE_SETUSERCONTEXT */ /* * Destroy environment. * We need to do this before setusercontext() because that may * set or reset some environment variables. */ if (!(environ = initStrArr( 0 ))) goto cError; /* * Set the user's credentials: uid, gid, groups, * environment variables, resource limits, and umask. */ if (setusercontext( lc, p, p->pw_uid, LOGIN_SETALL & ~(D_LOGIN_SETGROUP|D_LOGIN_SETLOGIN) ) < 0) { logError( "setusercontext for %s failed: %m\n", curuser ); goto cError; } for (i = 0; environ[i]; i++) userEnviron = putEnv( environ[i], userEnviron ); # endif /* !HAVE_SETUSERCONTEXT */ #else /* PAM || !_AIX */ /* * Set the user's credentials: uid, gid, groups, * audit classes, user limits, and umask. */ if (setpcred( curuser, NULL ) == -1) { logError( "setpcred for %s failed: %m\n", curuser ); goto cError; } /* * Set the users process environment. Store protected variables and * obtain updated user environment list. This call will initialize * global 'newenv'. */ if (setpenv( curuser, PENV_INIT | PENV_ARGV | PENV_NOEXEC, userEnviron, NULL ) != 0) { logError( "Cannot set %s's process environment\n", curuser ); goto cError; } userEnviron = newenv; #endif /* _AIX */ /* * for user-based authorization schemes, * use the password to get the user's credentials. */ #ifdef SECURE_RPC /* do like "keylogin" program */ if (!curpass[0]) logInfo( "No password for NIS provided.\n" ); else { char netname[MAXNETNAMELEN+1], secretkey[HEXKEYBYTES+1]; int nameret, keyret; int len; int key_set_ok = 0; struct key_netstarg netst; nameret = getnetname( netname ); debug( "user netname: %s\n", netname ); len = strlen( curpass ); if (len > 8) bzero( curpass + 8, len - 8 ); keyret = getsecretkey( netname, secretkey, curpass ); debug( "getsecretkey returns %d, key length %d\n", keyret, strlen( secretkey ) ); netst.st_netname = netname; memcpy( netst.st_priv_key, secretkey, HEXKEYBYTES ); memset( netst.st_pub_key, 0, HEXKEYBYTES ); if (key_setnet( &netst ) < 0) debug( "Could not set secret key.\n" ); /* is there a key, and do we have the right password? */ if (keyret == 1) { if (*secretkey) { keyret = key_setsecret( secretkey ); debug( "key_setsecret returns %d\n", keyret ); if (keyret == -1) logError( "Failed to set NIS secret key\n" ); else key_set_ok = 1; } else { /* found a key, but couldn't interpret it */ logError( "Password incorrect for NIS principal %s\n", nameret ? netname : curuser ); } } if (!key_set_ok) nukeAuth( 9, "SUN-DES-1" ); bzero( secretkey, strlen( secretkey ) ); } #endif #ifdef K5AUTH /* do like "kinit" program */ if (!curpass[0]) logInfo( "No password for Kerberos5 provided.\n" ); else if ((str = krb5Init( curuser, curpass, td->name ))) userEnviron = setEnv( userEnviron, "KRB5CCNAME", str ); else nukeAuth( 14, "MIT-KERBEROS-5" ); #endif /* K5AUTH */ if (td->autoReLogin) { gSet( &mstrtalk ); gSendInt( D_ReLogin ); gSendStr( curuser ); gSendStr( curpass ); gSendStr( newdmrc ); } if (curpass) bzero( curpass, strlen( curpass ) ); setUserAuthorization( td ); home = getEnv( userEnviron, "HOME" ); if (home && chdir( home ) < 0) { logError( "Cannot chdir to %s's home %s: %m\n", curuser, home ); sendStr( V_MSG_ERR, "Cannot enter home directory. Using /.\n" ); chdir( "/" ); userEnviron = setEnv( userEnviron, "HOME", "/" ); home = 0; } if (home || td->clientLogFile[0] == '/') { if (!createClientLog( td->clientLogFile )) { logWarn( "Session log file according to %s cannot be created: %m\n", td->clientLogFile ); goto tmperr; } } else { tmperr: if (!createClientLog( td->clientLogFallback )) logError( "Fallback session log file according to %s cannot be created: %m\n", td->clientLogFallback ); /* Could inform the user, but I guess this is only confusing. */ } if (!*dmrcDir) mergeSessionArgs( home != 0 ); if (!(desksess = iniEntry( curdmrc, "Desktop", "Session", 0 ))) desksess = "failsafe"; /* only due to OOM */ gSet( &mstrtalk ); gSendInt( D_User ); gSendInt( curuid ); gSendStr( curuser ); gSendStr( desksess ); close( mstrtalk.pipe->fd.w ); userEnviron = setEnv( userEnviron, "DESKTOP_SESSION", desksess ); for (i = 0; td->sessionsDirs[i]; i++) { fname = 0; if (strApp( &fname, td->sessionsDirs[i], "/", desksess, ".desktop", (char *)0 )) { if ((str = iniLoad( fname ))) { if (!strCmp( iniEntry( str, "Desktop Entry", "Hidden", 0 ), "true" ) || !(sessargs = iniEntry( str, "Desktop Entry", "Exec", 0 ))) sessargs = ""; free( str ); free( fname ); goto gotit; } free( fname ); } } if (!strcmp( desksess, "failsafe" ) || !strcmp( desksess, "default" ) || !strcmp( desksess, "custom" )) sessargs = desksess; else sessargs = ""; gotit: if (!(argv = parseArgs( (char **)0, td->session )) || !(argv = addStrArr( argv, sessargs, -1 ))) exit( 1 ); if (argv[0] && *argv[0]) { debug( "executing session %\"[s\n", argv ); execute( argv, userEnviron ); logError( "Session %\"s execution failed: %m\n", argv[0] ); } else logError( "Session has no command/arguments\n" ); failsafeArgv[0] = td->failsafeClient; failsafeArgv[1] = 0; execute( failsafeArgv, userEnviron ); logError( "Failsafe client %\"s execution failed: %m\n", failsafeArgv[0] ); cError: sendStr( V_MSG_ERR, 0 ); exit( 1 ); case -1: free( buf ); return 0; } debug( "StartSession, fork succeeded %d\n", *pid ); free( buf ); gSet( &ctltalk ); if (!Setjmp( ctltalk.errjmp )) while (gRecvCmd( &i )) { buf = gRecvStr(); displayStr( i, buf ); free( buf ); gSet( &ctltalk ); gSendInt( 0 ); } gClosen( ctltalk.pipe ); finishGreet(); return 1; }
int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display) { /* code adapted from Xlib/ConnDis.c, xtrans/Xtranssocket.c, xtrans/Xtransutils.c */ struct sockaddr *sockname = NULL; int gotsockname = 0; Xauth *authptr = 0; int ret = 1; /* Some systems like hpux or Hurd do not expose peer names * for UNIX Domain Sockets, but this is irrelevant, * since compute_auth() ignores the peer name in this * case anyway.*/ if ((sockname = get_peer_sock_name(getpeername, fd)) == NULL) { if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL) return 0; /* can only authenticate sockets */ if (sockname->sa_family != AF_UNIX) { free(sockname); return 0; /* except for AF_UNIX, sockets should have peernames */ } gotsockname = 1; } authptr = get_authptr(sockname, display); if (authptr == 0) { free(sockname); return 0; /* cannot find good auth data */ } info->namelen = memdup(&info->name, authptr->name, authptr->name_length); if (!info->namelen) goto no_auth; /* out of memory */ if (!gotsockname) { free(sockname); if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL) { free(info->name); goto no_auth; /* can only authenticate sockets */ } } ret = compute_auth(info, authptr, sockname); if(!ret) { free(info->name); goto no_auth; /* cannot build auth record */ } free(sockname); sockname = NULL; XauDisposeAuth(authptr); return ret; no_auth: free(sockname); info->name = 0; info->namelen = 0; XauDisposeAuth(authptr); return 0; }
Xauth * XauGetBestAuthByAddr ( #if NeedWidePrototypes unsigned int family, unsigned int address_length, #else unsigned short family, unsigned short address_length, #endif _Xconst char* address, #if NeedWidePrototypes unsigned int number_length, #else unsigned short number_length, #endif _Xconst char* number, int types_length, char** types, _Xconst int* type_lengths) { FILE *auth_file; char *auth_name; Xauth *entry; Xauth *best; int best_type; int type; auth_name = XauFileName (); if (!auth_name) return 0; if (access (auth_name, R_OK) != 0) /* checks REAL id */ return 0; auth_file = fopen (auth_name, "rb"); if (!auth_file) return 0; best = 0; best_type = types_length; for (;;) { entry = XauReadAuth (auth_file); if (!entry) break; /* * Match when: * either family or entry->family are FamilyWild or * family and entry->family are the same and * address and entry->address are the same * and * either number or entry->number are empty or * number and entry->number are the same * and * either name or entry->name are empty or * name and entry->name are the same */ if ((family == FamilyWild || entry->family == FamilyWild || (entry->family == family && ((address_length == entry->address_length && binaryEqual (entry->address, address, (int)address_length)) ))) && (number_length == 0 || entry->number_length == 0 || (number_length == entry->number_length && binaryEqual (entry->number, number, (int)number_length)))) { if (best_type == 0) { best = entry; break; } for (type = 0; type < best_type; type++) if (type_lengths[type] == entry->name_length && !(strncmp (types[type], entry->name, entry->name_length))) { break; } if (type < best_type) { if (best) XauDisposeAuth (best); best = entry; best_type = type; if (type == 0) break; continue; } } XauDisposeAuth (entry); } (void) fclose (auth_file); return best; }
static gboolean gdm_authenticate_connection (GdmProtocolData *data) { #define GDM_MIT_MAGIC_COOKIE_LEN 16 const char *xau_path; FILE *f; Xauth *xau; char *display_number; gboolean retval; if (data->auth_cookie) { char *msg; char *response; msg = g_strdup_printf (GDM_PROTOCOL_MSG_AUTHENTICATE " %s", data->auth_cookie); response = gdm_send_protocol_msg (data, msg); g_free (msg); if (response && !strcmp (response, "OK")) { g_free (response); return TRUE; } else { g_free (response); g_free (data->auth_cookie); data->auth_cookie = NULL; } } if (!(xau_path = XauFileName ())) return FALSE; if (!(f = fopen (xau_path, "r"))) return FALSE; retval = FALSE; display_number = get_display_number (); while ((xau = XauReadAuth (f))) { char buffer[40]; /* 2*16 == 32, so 40 is enough */ char *msg; char *response; int i; if (xau->family != FamilyLocal || strncmp (xau->number, display_number, xau->number_length) || strncmp (xau->name, "MIT-MAGIC-COOKIE-1", xau->name_length) || xau->data_length != GDM_MIT_MAGIC_COOKIE_LEN) { XauDisposeAuth (xau); continue; } for (i = 0; i < GDM_MIT_MAGIC_COOKIE_LEN; i++) g_snprintf (buffer + 2*i, 3, "%02x", (guint)(guchar)xau->data[i]); XauDisposeAuth (xau); msg = g_strdup_printf (GDM_PROTOCOL_MSG_AUTHENTICATE " %s", buffer); response = gdm_send_protocol_msg (data, msg); g_free (msg); if (response && !strcmp (response, "OK")) { data->auth_cookie = g_strdup (buffer); g_free (response); retval = TRUE; break; } g_free (response); } g_free (display_number); fclose (f); return retval; #undef GDM_MIT_MAGIC_COOKIE_LEN }
/* If ADD-ENTRIES is true, merge our auth entries into the existing Xauthority file. If ADD-ENTRIES is false, remove our entries. */ static int write_auth_file (int add_entries) { char *home, newname[1024]; int fd, ret; FILE *new_fh, *old_fh; addr_list *addr; Xauth *auth; if (auth_file == NULL) return FALSE; home = getenv ("HOME"); if (home == NULL) { auth_file = NULL; return FALSE; } snprintf (newname, sizeof (newname), "%s/.XauthorityXXXXXX", home); mktemp (newname); if (XauLockAuth (auth_file, 1, 2, 10) != LOCK_SUCCESS) { /* FIXME: do something here? */ auth_file = NULL; return FALSE; } fd = open (newname, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd >= 0) { new_fh = fdopen (fd, "w"); if (new_fh != NULL) { if (add_entries) { for (addr = addresses; addr != NULL; addr = addr->next) { XauWriteAuth (new_fh, &addr->auth); } } old_fh = fopen (auth_file, "r"); if (old_fh != NULL) { while ((auth = XauReadAuth (old_fh)) != NULL) { if (!check_auth_item (auth)) XauWriteAuth (new_fh, auth); XauDisposeAuth (auth); } fclose (old_fh); } fclose (new_fh); unlink (auth_file); ret = rename (newname, auth_file); if (ret != 0) auth_file = NULL; XauUnlockAuth (auth_file); return ret == 0; } close (fd); } XauUnlockAuth (auth_file); auth_file = NULL; return FALSE; }
static int do_add(const char *inputfilename, int lineno, int argc, const char **argv) { int n, nnew, nrepl; int len; const char *dpyname; const char *protoname; const char *hexkey; char *key; AuthList *list, *list_cur, *list_next; if (argc != 4 || !argv[1] || !argv[2] || !argv[3]) { prefix (inputfilename, lineno); badcommandline (argv[0]); return 1; } dpyname = argv[1]; protoname = argv[2]; hexkey = argv[3]; len = strlen(hexkey); if (hexkey[0] == '"' && hexkey[len-1] == '"') { key = malloc(len-1); strncpy(key, hexkey+1, len-2); len -= 2; } else if (!strcmp(protoname, SECURERPC) || !strcmp(protoname, K5AUTH)) { key = malloc(len+1); strcpy(key, hexkey); } else { len = cvthexkey (hexkey, &key); if (len < 0) { prefix (inputfilename, lineno); fprintf (stderr, "key contains odd number of or non-hex characters\n"); return 1; } } if (!get_displayname_auth (dpyname, &list)) { prefix (inputfilename, lineno); baddisplayname (dpyname, argv[0]); free (key); return 1; } /* * allow an abbreviation for common protocol names */ if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV) == 0) { protoname = DEFAULT_PROTOCOL; } for (list_cur = list; list_cur != NULL; list_cur = list_cur->next) { Xauth *auth = list_cur->auth; auth->name_length = strlen (protoname); auth->name = copystring (protoname, auth->name_length); if (!auth->name) { prefix (inputfilename, lineno); fprintf (stderr, "unable to allocate %d character protocol name\n", auth->name_length); for (list_cur = list; list_cur != NULL; list_cur = list_next) { list_next = list_cur->next; XauDisposeAuth(list_cur->auth); free(list_cur); } free (key); return 1; } auth->data_length = len; auth->data = malloc(len); if (!auth->data) { prefix(inputfilename, lineno); fprintf(stderr, "unable to allocate %d bytes for key\n", len); for (list_cur = list; list_cur != NULL; list_cur = list_next) { list_next = list_cur->next; XauDisposeAuth(list_cur->auth); free(list_cur); } free(key); return 1; } memcpy(auth->data, key, len); } free(key); /* * merge it in; note that merge will deal with allocation */ n = merge_entries (&xauth_head, list, &nnew, &nrepl); if (n <= 0) { prefix (inputfilename, lineno); fprintf (stderr, "unable to merge in added record\n"); return 1; } xauth_modified = True; return 0; }
static int iterdpy (const char *inputfilename, int lineno, int start, int argc, const char *argv[], YesNoFunc yfunc, YesNoFunc nfunc, char *data) { int i; int status; int errors = 0; Xauth *tmp_auth; AuthList *proto_head, *proto; AuthList *l, *next; /* * iterate */ for (i = start; i < argc; i++) { const char *displayname = argv[i]; if (!get_displayname_auth (displayname, &proto_head)) { prefix (inputfilename, lineno); baddisplayname (displayname, argv[0]); errors++; continue; } status = 0; for (l = xauth_head; l; l = next) { Bool matched = False; /* l may be freed by remove_entry below. so save its contents */ next = l->next; tmp_auth = copyAuth(l->auth); for (proto = proto_head; proto; proto = proto->next) { if (match_auth_dpy (proto->auth, tmp_auth)) { matched = True; if (yfunc) { status = (*yfunc) (inputfilename, lineno, tmp_auth, data); if (status < 0) break; } } } XauDisposeAuth(tmp_auth); if (matched == False) { if (nfunc) { status = (*nfunc) (inputfilename, lineno, l->auth, data); } } if (status < 0) break; } for (proto = proto_head; proto ; proto = next) { next = proto->next; if (proto->auth->address) free (proto->auth->address); if (proto->auth->number) free (proto->auth->number); free (proto->auth); free (proto); } if (status < 0) { errors -= status; /* since status is negative */ break; } } return errors; }
Xauth * XauGetBestAuthByAddr ( #if NeedWidePrototypes unsigned int family, unsigned int address_length, #else unsigned short family, unsigned short address_length, #endif _Xconst char* address, #if NeedWidePrototypes unsigned int number_length, #else unsigned short number_length, #endif _Xconst char* number, int types_length, char** types, _Xconst int* type_lengths) { FILE *auth_file; char *auth_name; Xauth *entry; Xauth *best; int best_type; int type; #ifdef hpux char *fully_qual_address; unsigned short fully_qual_address_length; #endif auth_name = XauFileName (); if (!auth_name) return NULL; if (access (auth_name, R_OK) != 0) /* checks REAL id */ return NULL; auth_file = fopen (auth_name, "rb"); if (!auth_file) return NULL; #ifdef hpux if (family == FamilyLocal) { #ifdef XTHREADS_NEEDS_BYNAMEPARAMS _Xgethostbynameparams hparams; #endif struct hostent *hostp; /* make sure we try fully-qualified hostname */ if ((hostp = _XGethostbyname(address,hparams)) != NULL) { fully_qual_address = hostp->h_name; fully_qual_address_length = strlen(fully_qual_address); } else { fully_qual_address = NULL; fully_qual_address_length = 0; } } #endif /* hpux */ best = NULL; best_type = types_length; for (;;) { entry = XauReadAuth (auth_file); if (!entry) break; /* * Match when: * either family or entry->family are FamilyWild or * family and entry->family are the same and * address and entry->address are the same * and * either number or entry->number are empty or * number and entry->number are the same * and * either name or entry->name are empty or * name and entry->name are the same */ if ((family == FamilyWild || entry->family == FamilyWild || (entry->family == family && ((address_length == entry->address_length && binaryEqual (entry->address, address, (int)address_length)) #ifdef hpux || (family == FamilyLocal && fully_qual_address_length == entry->address_length && binaryEqual (entry->address, fully_qual_address, (int) fully_qual_address_length)) #endif ))) && (number_length == 0 || entry->number_length == 0 || (number_length == entry->number_length && binaryEqual (entry->number, number, (int)number_length)))) { if (best_type == 0) { best = entry; break; } for (type = 0; type < best_type; type++) if (type_lengths[type] == entry->name_length && !(strncmp (types[type], entry->name, entry->name_length))) { break; } if (type < best_type) { if (best) XauDisposeAuth (best); best = entry; best_type = type; if (type == 0) break; continue; } } XauDisposeAuth (entry); } (void) fclose (auth_file); return best; }
/******************************************************************** * * fork/exec a child pdm after setting up a message pipe. */ void mgr_launch_pdm( XpPdmServiceRec *rec ) { int i; struct sigaction svec; char buf[1024]; int original_umask; char *existing_name; FILE *existing_file; Xauth *entry; char *envstr; /* * Setup message pipe. */ if ( pipe(rec->message_pipe) == -1 ) { rec->pdm_exec_errorcode = g.pdm_start_error; sprintf( buf, PDMD_MSG_8, g.prog_name ); rec->pdm_exec_errormessage = xpstrdup( buf ); return; } rec->message_xtid = XtAppAddInput( g.context, rec->message_pipe[0], (XtPointer) XtInputReadMask, message_pipe_handler, (XtPointer) NULL ); /* * See if a cookie file is needed. */ if (rec->cookie_cnt) { /* * Create new .Xauthority file. */ original_umask = umask (0077); /* disallow non-owner access */ tmpnam( rec->auth_filename ); rec->auth_file = fopen( rec->auth_filename, "w" ); if (rec->auth_file) { /* * Copy existing .Xauthority entries. */ existing_name = XauFileName (); if (existing_name) { if (access (existing_name, R_OK) == 0) { /* checks REAL id */ existing_file = fopen (existing_name, "r"); if (existing_file) { for (;;) { entry = XauReadAuth (existing_file); if (!entry) break; XauWriteAuth( rec->auth_file, entry ); XauDisposeAuth (entry); } fclose (existing_file); } } } /* * Merge in cookies recently sent. */ for ( i = 0; i < rec->cookie_cnt; i++ ) { XauWriteAuth( rec->auth_file, rec->cookies[i] ); } fclose( rec->auth_file ); } original_umask = umask (original_umask); } rec->pid = fork(); if ( rec->pid < 0 ) { rec->pdm_exec_errorcode = g.pdm_start_error; sprintf( buf, PDMD_MSG_9, g.prog_name ); rec->pdm_exec_errormessage = xpstrdup( buf ); return; } else if ( rec->pid == 0) { /* * Child process. */ /* * Hook stderr back to parent via message pipe. */ dup2(rec->message_pipe[1], 2); close(rec->message_pipe[0]); /* * The child should have default behavior for all signals. */ sigemptyset(&svec.sa_mask); svec.sa_flags = 0; svec.sa_handler = SIG_DFL; (void) sigaction(SIGCHLD, &svec, (struct sigaction *) NULL); for (i=3; i < FOPEN_MAX; i++) { if ((i != rec->message_pipe[1]) && (rec->auth_file && (i != fileno(rec->auth_file)))) { (void) fcntl (i, F_SETFD, 1); } } /* * Set the new locale for the child. * * note: the locale hint will be of the form: * * name_spec[;registry_spec[;ver_spec[;encoding_spec]]] * * for now, just pull out the name_spec (e.g. 'C') * and use it. With a little work, a more complex * syntax could be understood and the appropriate * actions taken here rather than just wedging * name_spec into setlocale() and hoping. */ if ( !(rec->locale_hint) ) { /* * Leave current locale alone. */ } else if ( strcmp( rec->locale_hint, "" ) ) { /* * Leave current locale alone. Note that "" into * setlocale says to go with default vs leave it alone. */ } else { char *tptr1, *tptr2; tptr1 = xpstrdup( rec->locale_hint ); tptr2 = strchr( tptr1, ';' ); if (tptr2) *tptr2 = '\0'; setlocale( LC_ALL, tptr1 ); XFree( tptr1 ); } /* * Set XAUTHORITY env var if needed. */ if ((rec->cookie_cnt) && (rec->auth_filename) && (rec->auth_file)) { envstr = Xmalloc( strlen(rec->auth_filename) + 12 ); sprintf( envstr, "XAUTHORITY=%s", rec->auth_filename ); putenv( envstr ); } /* * Start the child for real. */ (void) execvp(rec->pdm_exec_argvs[0], rec->pdm_exec_argvs); (void) fprintf (stderr, PDMD_MSG_10, g.prog_name, rec->pdm_exec_argvs[0]); /* * tomg - need to deal with failed child start. */ exit(PDM_EXIT_ERROR); } else { /* * Parent process. */ /* * Close the write end of the pipe - only the child needs it. */ close(rec->message_pipe[1]); rec->message_pipe[1] = -1; } }