auth.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: auth.c /main/6 1997/03/14 13:44:25 barstow $ */
  24. /* (c) Copyright 1997 The Open Group */
  25. /* *
  26. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  27. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  28. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  29. * (c) Copyright 1993, 1994 Novell, Inc. *
  30. */
  31. /*
  32. * @DEC_COPYRIGHT@
  33. */
  34. /*
  35. * HISTORY
  36. * $Log$
  37. * Revision 1.1.2.3 1995/06/06 20:21:58 Chris_Beute
  38. * Code snapshot merge from March 15 and SIA changes
  39. * [1995/05/31 20:09:58 Chris_Beute]
  40. *
  41. * Revision 1.1.2.2 1995/04/21 13:05:15 Peter_Derr
  42. * dtlogin auth key fixes from deltacde
  43. * [1995/04/12 19:20:51 Peter_Derr]
  44. *
  45. * R6 version of auth.c to handle multiple authentication protocols.
  46. * [1995/04/12 18:05:30 Peter_Derr]
  47. *
  48. * $EndLog$
  49. */
  50. /*
  51. Copyright (c) 1988 X Consortium
  52. Permission is hereby granted, free of charge, to any person obtaining
  53. a copy of this software and associated documentation files (the
  54. "Software"), to deal in the Software without restriction, including
  55. without limitation the rights to use, copy, modify, merge, publish,
  56. distribute, sublicense, and/or sell copies of the Software, and to
  57. permit persons to whom the Software is furnished to do so, subject to
  58. the following conditions:
  59. The above copyright notice and this permission notice shall be included
  60. in all copies or substantial portions of the Software.
  61. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  62. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  63. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  64. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
  65. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  66. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  67. OTHER DEALINGS IN THE SOFTWARE.
  68. Except as contained in this notice, the name of the X Consortium shall
  69. not be used in advertising or otherwise to promote the sale, use or
  70. other dealings in this Software without prior written authorization
  71. from the X Consortium.
  72. */
  73. /*
  74. * xdm - display manager daemon
  75. * Author: Keith Packard, MIT X Consortium
  76. *
  77. * auth.c
  78. *
  79. * maintain the authorization generation daemon
  80. */
  81. #include "dm.h"
  82. #include "vgmsg.h"
  83. #include <X11/X.h>
  84. #include <sys/types.h>
  85. #include <sys/stat.h>
  86. #include <errno.h>
  87. #ifdef X_NOT_STDC_ENV
  88. extern int errno;
  89. #endif
  90. #include <sys/socket.h>
  91. #ifndef ESIX
  92. # include <sys/ioctl.h>
  93. #endif /* !ESIX */
  94. #ifdef TCPCONN
  95. # include <netinet/in.h>
  96. #endif
  97. #ifdef DNETCONN
  98. # include <netdnet/dn.h>
  99. # include <netdnet/dnetdb.h>
  100. #endif
  101. #if (defined(_POSIX_SOURCE) && !defined(AIXV3)) || defined(SVR4)
  102. #define NEED_UTSNAME
  103. #include <sys/utsname.h>
  104. #endif
  105. #if defined(SYSV) && defined(SYSV386)
  106. # include <sys/stream.h>
  107. # ifdef ISC
  108. # include <sys/sioctl.h>
  109. # endif /* ISC */
  110. # ifdef ESIX
  111. # include <lan/net_ioctl.h>
  112. # endif /* ESIX */
  113. #endif /* SYSV386 */
  114. #ifdef SVR4
  115. # include <netdb.h>
  116. # include <sys/sockio.h>
  117. #endif
  118. #ifdef __convex__
  119. # include <sync/queue.h>
  120. # include <sync/sema.h>
  121. #endif
  122. #include <net/if.h>
  123. #ifdef SECURE_RPC
  124. extern int SecureRPCInitAuth ();
  125. extern Xauth *SecureRPCGetAuth ();
  126. #endif
  127. #ifdef K5AUTH
  128. extern int Krb5InitAuth ();
  129. extern Xauth *Krb5GetAuth ();
  130. #endif
  131. struct AuthProtocol {
  132. unsigned short name_length;
  133. char *name;
  134. int (*InitAuth)(
  135. #if NeedWidePrototypes
  136. unsigned int name_len,
  137. #else
  138. unsigned short name_len,
  139. #endif /* NeedWidePrototypes */
  140. char *name) ;
  141. Xauth *(*GetAuth)(
  142. #if NeedWidePrototypes
  143. unsigned int namelen,
  144. #else
  145. unsigned short namelen,
  146. #endif /* NeedWidePrototypes */
  147. char *name) ;
  148. void (*GetXdmcpAuth)();
  149. int inited;
  150. };
  151. static struct AuthProtocol AuthProtocols[] = {
  152. { (unsigned short) 18, "MIT-MAGIC-COOKIE-1",
  153. MitInitAuth, MitGetAuth, NULL
  154. },
  155. #ifdef HASXDMAUTH
  156. { (unsigned short) 19, "XDM-AUTHORIZATION-1",
  157. XdmInitAuth, XdmGetAuth, XdmGetXdmcpAuth,
  158. },
  159. #endif
  160. #ifdef SECURE_RPC
  161. { (unsigned short) 9, "SUN-DES-1",
  162. SecureRPCInitAuth, SecureRPCGetAuth, NULL,
  163. },
  164. #endif
  165. #ifdef K5AUTH
  166. { (unsigned short) 14, "MIT-KERBEROS-5",
  167. Krb5InitAuth, Krb5GetAuth, NULL,
  168. },
  169. #endif
  170. };
  171. #define NUM_AUTHORIZATION (sizeof (AuthProtocols) / sizeof (AuthProtocols[0]))
  172. static struct AuthProtocol *
  173. findProtocol (unsigned short name_length, const char *name)
  174. {
  175. int i;
  176. for (i = 0; i < NUM_AUTHORIZATION; i++)
  177. if (AuthProtocols[i].name_length == name_length &&
  178. memcmp(AuthProtocols[i].name, name, name_length) == 0)
  179. {
  180. return &AuthProtocols[i];
  181. }
  182. return (struct AuthProtocol *) 0;
  183. }
  184. #if NeedWidePrototypes
  185. int
  186. ValidAuthorization (unsigned int name_length, char *name)
  187. #else
  188. int
  189. ValidAuthorization (unsigned short name_length, char *name)
  190. #endif /* NeedWidePrototypes */
  191. {
  192. if (findProtocol (name_length, name))
  193. return TRUE;
  194. return FALSE;
  195. }
  196. static Xauth *
  197. GenerateAuthorization (unsigned short name_length, char *name)
  198. {
  199. struct AuthProtocol *a;
  200. Xauth *auth = 0;
  201. int i;
  202. Debug ("GenerateAuthorization %*.*s\n",
  203. name_length, name_length, name);
  204. a = findProtocol (name_length, name);
  205. if (a)
  206. {
  207. if (!a->inited)
  208. {
  209. (*a->InitAuth) (name_length, name);
  210. a->inited = TRUE;
  211. }
  212. auth = (*a->GetAuth) (name_length, name);
  213. if (auth)
  214. {
  215. Debug ("Got 0x%x (%d %*.*s) ", auth,
  216. auth->name_length, auth->name_length,
  217. auth->name_length, auth->name);
  218. for (i = 0; i < (int)auth->data_length; i++)
  219. Debug (" %02x", auth->data[i] & 0xff);
  220. Debug ("\n");
  221. }
  222. else
  223. Debug ("Got (null)\n");
  224. }
  225. else
  226. {
  227. Debug ("Unknown authorization %*.*s\n", name_length, name_length, name);
  228. }
  229. return auth;
  230. }
  231. #if NeedWidePrototypes
  232. void
  233. SetProtoDisplayAuthorization (struct protoDisplay *pdpy, unsigned int authorizationNameLen, char *authorizationName)
  234. #else
  235. void
  236. SetProtoDisplayAuthorization (struct protoDisplay *pdpy, unsigned short authorizationNameLen, char *authorizationName)
  237. #endif /* NeedWidePrototypes */
  238. {
  239. struct AuthProtocol *a;
  240. Xauth *auth;
  241. a = findProtocol (authorizationNameLen, authorizationName);
  242. pdpy->xdmcpAuthorization = pdpy->fileAuthorization = 0;
  243. if (a)
  244. {
  245. if (!a->inited)
  246. {
  247. (*a->InitAuth) (authorizationNameLen, authorizationName);
  248. a->inited = TRUE;
  249. }
  250. if (a->GetXdmcpAuth)
  251. {
  252. (*a->GetXdmcpAuth) (pdpy, authorizationNameLen, authorizationName);
  253. auth = pdpy->xdmcpAuthorization;
  254. }
  255. else
  256. {
  257. auth = (*a->GetAuth) (authorizationNameLen, authorizationName);
  258. pdpy->fileAuthorization = auth;
  259. pdpy->xdmcpAuthorization = 0;
  260. }
  261. if (auth)
  262. Debug ("Got 0x%x (%d %*.*s)\n", auth,
  263. auth->name_length, auth->name_length,
  264. auth->name_length, auth->name);
  265. else
  266. Debug ("Got (null)\n");
  267. }
  268. }
  269. void
  270. CleanUpFileName (char *src, char *dst, int len)
  271. {
  272. while (*src) {
  273. if (--len <= 0)
  274. break;
  275. switch (*src & 0x7f)
  276. {
  277. case '/':
  278. *dst++ = '_';
  279. break;
  280. case '-':
  281. *dst++ = '.';
  282. break;
  283. default:
  284. *dst++ = (*src & 0x7f);
  285. }
  286. ++src;
  287. }
  288. *dst = '\0';
  289. }
  290. static char authdir1[] = "authdir";
  291. static char authdir2[] = "authfiles";
  292. static int
  293. MakeServerAuthFile (struct display *d)
  294. {
  295. int len;
  296. #ifdef SYSV
  297. #define NAMELEN 14
  298. #else
  299. #define NAMELEN 255
  300. #endif
  301. char cleanname[NAMELEN];
  302. int r;
  303. struct stat statb;
  304. if (d->clientAuthFile && *d->clientAuthFile)
  305. len = strlen (d->clientAuthFile) + 1;
  306. else
  307. {
  308. CleanUpFileName (d->name, cleanname, NAMELEN - 8);
  309. len = strlen (authDir) + strlen (authdir1) + strlen (authdir2)
  310. + strlen (cleanname) + 14;
  311. }
  312. if (d->authFile)
  313. free (d->authFile);
  314. d->authFile = malloc ((unsigned) len);
  315. if (!d->authFile)
  316. return FALSE;
  317. if (d->clientAuthFile && *d->clientAuthFile)
  318. strcpy (d->authFile, d->clientAuthFile);
  319. else
  320. {
  321. sprintf (d->authFile, "%s/%s", authDir, authdir1);
  322. r = stat(d->authFile, &statb);
  323. if (r == 0) {
  324. if (statb.st_uid != 0) {
  325. if(-1 == chown(d->authFile, 0, statb.st_gid)) {
  326. perror(strerror(errno));
  327. return FALSE;
  328. }
  329. }
  330. if ((statb.st_mode & 0077) != 0) {
  331. if(-1 == chmod(d->authFile, statb.st_mode & 0700)) {
  332. perror(strerror(errno));
  333. return FALSE;
  334. }
  335. }
  336. } else {
  337. if (errno == ENOENT)
  338. r = mkdir(d->authFile, 0700);
  339. if (r < 0) {
  340. free (d->authFile);
  341. d->authFile = NULL;
  342. return FALSE;
  343. }
  344. }
  345. sprintf (d->authFile, "%s/%s/%s", authDir, authdir1, authdir2);
  346. r = mkdir(d->authFile, 0700);
  347. if (r < 0 && errno != EEXIST) {
  348. free (d->authFile);
  349. d->authFile = NULL;
  350. return FALSE;
  351. }
  352. sprintf (d->authFile, "%s/%s/%s/A%s-XXXXXX",
  353. authDir, authdir1, authdir2, cleanname);
  354. (void) mktemp (d->authFile);
  355. }
  356. return TRUE;
  357. }
  358. int
  359. SaveServerAuthorizations (struct display *d, Xauth **auths, int count)
  360. {
  361. FILE *auth_file;
  362. int mask;
  363. int ret;
  364. int i;
  365. mask = umask (0077);
  366. if (!d->authFile && !MakeServerAuthFile (d))
  367. return FALSE;
  368. (void) unlink (d->authFile);
  369. auth_file = fopen (d->authFile, "w");
  370. umask (mask);
  371. if (!auth_file) {
  372. Debug ("Can't creat auth file %s\n", d->authFile);
  373. LogError (ReadCatalog(MC_LOG_SET,MC_LOG_SRV_OPEN,MC_DEF_LOG_SRV_OPEN),
  374. d->authFile);
  375. free (d->authFile);
  376. d->authFile = NULL;
  377. ret = FALSE;
  378. }
  379. else
  380. {
  381. Debug ("File: %s auth: %x\n", d->authFile, auths);
  382. ret = TRUE;
  383. for (i = 0; i < count; i++)
  384. {
  385. /*
  386. * User-based auths may not have data until
  387. * a user logs in. In which case don't write
  388. * to the auth file so xrdb and setup programs don't fail.
  389. */
  390. if (auths[i]->data_length > 0)
  391. if (!XauWriteAuth (auth_file, auths[i]) ||
  392. fflush (auth_file) == EOF)
  393. {
  394. LogError (
  395. ReadCatalog(MC_LOG_SET,MC_LOG_SRV_WRT,MC_DEF_LOG_SRV_WRT),
  396. d->authFile);
  397. ret = FALSE;
  398. free (d->authFile);
  399. d->authFile = NULL;
  400. }
  401. }
  402. fclose (auth_file);
  403. }
  404. return ret;
  405. }
  406. void
  407. SetLocalAuthorization (struct display *d)
  408. {
  409. Xauth *auth, **auths;
  410. int i, j;
  411. if (d->authorizations)
  412. {
  413. for (i = 0; i < d->authNum; i++)
  414. XauDisposeAuth (d->authorizations[i]);
  415. free ((char *) d->authorizations);
  416. d->authorizations = (Xauth **) NULL;
  417. d->authNum = 0;
  418. }
  419. if (!d->authNames)
  420. return;
  421. for (i = 0; d->authNames[i]; i++)
  422. ;
  423. d->authNameNum = i;
  424. if (d->authNameLens)
  425. free ((char *) d->authNameLens);
  426. d->authNameLens = (unsigned short *) malloc
  427. (d->authNameNum * sizeof (unsigned short));
  428. if (!d->authNameLens)
  429. return;
  430. for (i = 0; i < d->authNameNum; i++)
  431. d->authNameLens[i] = strlen (d->authNames[i]);
  432. auths = (Xauth **) malloc (d->authNameNum * sizeof (Xauth *));
  433. if (!auths)
  434. return;
  435. j = 0;
  436. for (i = 0; i < d->authNameNum; i++)
  437. {
  438. auth = GenerateAuthorization (d->authNameLens[i], d->authNames[i]);
  439. if (auth)
  440. auths[j++] = auth;
  441. }
  442. if (SaveServerAuthorizations (d, auths, j))
  443. {
  444. d->authorizations = auths;
  445. d->authNum = j;
  446. }
  447. else
  448. {
  449. for (i = 0; i < j; i++)
  450. XauDisposeAuth (auths[i]);
  451. free ((char *) auths);
  452. }
  453. }
  454. /*
  455. * Set the authorization to use for xdm's initial connection
  456. * to the X server. Cannot use user-based authorizations
  457. * because no one has logged in yet, so we don't have any
  458. * user credentials.
  459. * Well, actually we could use SUN-DES-1 because we tell the server
  460. * to allow root in. This is bogus and should be fixed.
  461. */
  462. void
  463. SetAuthorization (struct display *d)
  464. {
  465. Xauth **auth = d->authorizations;
  466. int i;
  467. for (i = 0; i < d->authNum; i++)
  468. {
  469. if (auth[i]->name_length == 9 &&
  470. memcmp(auth[i]->name, "SUN-DES-1", 9) == 0)
  471. continue;
  472. if (auth[i]->name_length == 14 &&
  473. memcmp(auth[i]->name, "MIT-KERBEROS-5", 14) == 0)
  474. continue;
  475. XSetAuthorization (auth[i]->name, (int) auth[i]->name_length,
  476. auth[i]->data, (int) auth[i]->data_length);
  477. }
  478. }
  479. static int
  480. openFiles (char *name, char *new_name, FILE **oldp, FILE **newp)
  481. {
  482. int mask;
  483. int null_data = 0;
  484. strcpy (new_name, name);
  485. strcat (new_name, "-n");
  486. mask = umask (0077);
  487. (void) unlink (new_name);
  488. *newp = fopen (new_name, "w");
  489. (void) umask (mask);
  490. if (!*newp) {
  491. Debug ("can't open new file %s\n", new_name);
  492. return 0;
  493. }
  494. /*
  495. * Make sure that the device is not 100% full by actually writing
  496. * to the file.
  497. */
  498. if ((sizeof(int) != fwrite(&null_data, 1, sizeof(int), *newp))
  499. || fflush(*newp)) {
  500. Debug ("can't write to new file %s\n", new_name);
  501. fclose(*newp);
  502. (void) unlink (new_name);
  503. return 0;
  504. }
  505. rewind(*newp);
  506. *oldp = fopen (name, "r");
  507. Debug ("opens succeeded %s %s\n", name, new_name);
  508. return 1;
  509. }
  510. int
  511. binaryEqual (char *a, char *b, unsigned short len)
  512. {
  513. while (len-- > 0)
  514. if (*a++ != *b++)
  515. return 0;
  516. return 1;
  517. }
  518. static void
  519. dumpBytes (unsigned short len, char *data)
  520. {
  521. unsigned short i;
  522. Debug ("%d: ", len);
  523. for (i = 0; i < len; i++)
  524. Debug ("%02x ", data[i] & 0377);
  525. Debug ("\n");
  526. }
  527. static void
  528. dumpAuth (Xauth *auth)
  529. {
  530. Debug ("family: %d\n", auth->family);
  531. Debug ("addr: ");
  532. dumpBytes (auth->address_length, auth->address);
  533. Debug ("number: ");
  534. dumpBytes (auth->number_length, auth->number);
  535. Debug ("name: ");
  536. dumpBytes (auth->name_length, auth->name);
  537. Debug ("data: ");
  538. dumpBytes (auth->data_length, auth->data);
  539. }
  540. struct addrList {
  541. unsigned short family;
  542. unsigned short address_length;
  543. char *address;
  544. unsigned short number_length;
  545. char *number;
  546. unsigned short name_length;
  547. char *name;
  548. struct addrList *next;
  549. };
  550. static struct addrList *addrs;
  551. static void
  552. initAddrs (void)
  553. {
  554. addrs = 0;
  555. }
  556. static void
  557. doneAddrs (void)
  558. {
  559. struct addrList *a, *n;
  560. for (a = addrs; a; a = n) {
  561. n = a->next;
  562. if (a->address)
  563. free (a->address);
  564. if (a->number)
  565. free (a->number);
  566. free ((char *) a);
  567. }
  568. }
  569. static int checkEntry (Xauth *auth);
  570. static void
  571. saveEntry (Xauth *auth)
  572. {
  573. struct addrList *new;
  574. new = (struct addrList *) malloc (sizeof (struct addrList));
  575. if (!new) {
  576. LogOutOfMem (ReadCatalog(
  577. MC_LOG_SET,MC_LOG_SAVE_ADDR,MC_DEF_LOG_SAVE_ADDR));
  578. return;
  579. }
  580. if ((new->address_length = auth->address_length) > 0) {
  581. new->address = malloc (auth->address_length);
  582. if (!new->address) {
  583. LogOutOfMem (ReadCatalog(
  584. MC_LOG_SET,MC_LOG_SAVE_ADDR,MC_DEF_LOG_SAVE_ADDR));
  585. free ((char *) new);
  586. return;
  587. }
  588. memmove( new->address, auth->address, (int) auth->address_length);
  589. } else
  590. new->address = 0;
  591. if ((new->number_length = auth->number_length) > 0) {
  592. new->number = malloc (auth->number_length);
  593. if (!new->number) {
  594. LogOutOfMem (ReadCatalog(
  595. MC_LOG_SET,MC_LOG_SAVE_ADDR,MC_DEF_LOG_SAVE_ADDR));
  596. free (new->address);
  597. free ((char *) new);
  598. return;
  599. }
  600. memmove( new->number, auth->number, (int) auth->number_length);
  601. } else
  602. new->number = 0;
  603. if ((new->name_length = auth->name_length) > 0) {
  604. new->name = malloc (auth->name_length);
  605. if (!new->name) {
  606. LogOutOfMem (ReadCatalog(
  607. MC_LOG_SET,MC_LOG_SAVE_ADDR,MC_DEF_LOG_SAVE_ADDR));
  608. free (new->number);
  609. free (new->address);
  610. free ((char *) new);
  611. return;
  612. }
  613. memmove( new->name, auth->name, (int) auth->name_length);
  614. } else
  615. new->name = 0;
  616. new->family = auth->family;
  617. new->next = addrs;
  618. addrs = new;
  619. }
  620. static int
  621. checkEntry (Xauth *auth)
  622. {
  623. struct addrList *a;
  624. for (a = addrs; a; a = a->next) {
  625. if (a->family == auth->family &&
  626. a->address_length == auth->address_length &&
  627. binaryEqual (a->address, auth->address, auth->address_length) &&
  628. a->number_length == auth->number_length &&
  629. binaryEqual (a->number, auth->number, auth->number_length) &&
  630. a->name_length == auth->name_length &&
  631. binaryEqual (a->name, auth->name, auth->name_length))
  632. {
  633. return 1;
  634. }
  635. }
  636. return 0;
  637. }
  638. static int doWrite;
  639. static int
  640. writeAuth (FILE *file, Xauth *auth)
  641. {
  642. if (debugLevel >= 15) { /* normally too verbose */
  643. Debug ("writeAuth: doWrite = %d\n", doWrite);
  644. dumpAuth (auth); /* does Debug only */
  645. }
  646. if (doWrite) {
  647. if (!XauWriteAuth (file, auth) || fflush (file) == EOF) {
  648. LogError(
  649. ReadCatalog(MC_LOG_SET,MC_LOG_SRV_WRT,MC_DEF_LOG_SRV_WRT),
  650. file);
  651. return 0;
  652. }
  653. else
  654. {
  655. return 1;
  656. }
  657. }
  658. return 1;
  659. }
  660. static void
  661. writeAddr (int family, int addr_length, char *addr, FILE *file, Xauth *auth)
  662. {
  663. auth->family = (unsigned short) family;
  664. auth->address_length = addr_length;
  665. auth->address = addr;
  666. Debug ("writeAddr: writing and saving an entry\n");
  667. writeAuth (file, auth);
  668. saveEntry (auth);
  669. }
  670. static void
  671. DefineLocal (FILE *file, Xauth *auth)
  672. {
  673. char displayname[100];
  674. /* stolen from xinit.c */
  675. /* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c.
  676. * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
  677. *
  678. * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
  679. * to have sufficient information for interfacing to the network,
  680. * and so, you may be better off using gethostname (if it exists).
  681. */
  682. #ifdef NEED_UTSNAME
  683. /*
  684. * Why not use gethostname()? Well, at least on my system, I've had to
  685. * make an ugly kernel patch to get a name longer than 8 characters, and
  686. * uname() lets me access to the whole string (it smashes release, you
  687. * see), whereas gethostname() kindly truncates it for me.
  688. */
  689. {
  690. struct utsname name;
  691. uname(&name);
  692. strcpy(displayname, name.nodename);
  693. }
  694. writeAddr (FamilyLocal, strlen (displayname), displayname, file, auth);
  695. #else
  696. /* AIXV3:
  697. * In AIXV3, _POSIX_SOURCE is defined, but uname gives only first
  698. * field of hostname. Thus, we use gethostname instead.
  699. */
  700. /*
  701. * For HP-UX, HP's Xlib expects a fully-qualified domain name, which
  702. * is achieved by using gethostname(). For compatability, we must
  703. * also still create the entry using uname() above.
  704. */
  705. gethostname(displayname, sizeof(displayname));
  706. writeAddr (FamilyLocal, strlen (displayname), displayname, file, auth);
  707. #endif
  708. }
  709. #ifdef WINTCP /* NCR with Wollongong TCP */
  710. #include <sys/un.h>
  711. #include <stropts.h>
  712. #include <tiuser.h>
  713. #include <sys/stream.h>
  714. #include <net/if.h>
  715. #include <netinet/ip.h>
  716. #include <netinet/ip_var.h>
  717. #include <netinet/in.h>
  718. #include <netinet/in_var.h>
  719. static void
  720. DefineSelf (int fd, FILE *file, Xauth *auth)
  721. {
  722. /*
  723. * The Wolongong drivers used by NCR SVR4/MP-RAS don't understand the
  724. * socket IO calls that most other drivers seem to like. Because of
  725. * this, this routine must be special cased for NCR. Eventually,
  726. * this will be cleared up.
  727. */
  728. struct ipb ifnet;
  729. struct in_ifaddr ifaddr;
  730. struct strioctl str;
  731. unsigned char *addr;
  732. int family, len, ipfd;
  733. if ((ipfd = open ("/dev/ip", O_RDWR, 0 )) < 0)
  734. LogError ((unsigned char *)"Getting interface configuration");
  735. /* Indicate that we want to start at the begining */
  736. ifnet.ib_next = (struct ipb *) 1;
  737. while (ifnet.ib_next)
  738. {
  739. str.ic_cmd = IPIOC_GETIPB;
  740. str.ic_timout = 0;
  741. str.ic_len = sizeof (struct ipb);
  742. str.ic_dp = (char *) &ifnet;
  743. if (ioctl (ipfd, (int) I_STR, (char *) &str) < 0)
  744. {
  745. close (ipfd);
  746. LogError ((unsigned char *) "Getting interface configuration");
  747. }
  748. ifaddr.ia_next = (struct in_ifaddr *) ifnet.if_addrlist;
  749. str.ic_cmd = IPIOC_GETINADDR;
  750. str.ic_timout = 0;
  751. str.ic_len = sizeof (struct in_ifaddr);
  752. str.ic_dp = (char *) &ifaddr;
  753. if (ioctl (ipfd, (int) I_STR, (char *) &str) < 0)
  754. {
  755. close (ipfd);
  756. LogError ((unsigned char *) "Getting interface configuration");
  757. }
  758. /*
  759. * Ignore the 127.0.0.1 entry.
  760. */
  761. if (IA_SIN(&ifaddr)->sin_addr.s_addr == htonl(0x7f000001) )
  762. continue;
  763. writeAddr (FamilyInternet, 4, (char *)&(IA_SIN(&ifaddr)->sin_addr), file, auth);
  764. }
  765. close(ipfd);
  766. }
  767. #else /* WINTCP */
  768. #ifdef SIOCGIFCONF
  769. /* think of something... */
  770. #define DECnetInstalled True
  771. /* Define this host for access control. Find all the hosts the OS knows about
  772. * for this fd and add them to the selfhosts list.
  773. */
  774. static void
  775. DefineSelf (int fd, FILE *file, Xauth *auth)
  776. {
  777. char buf[2048];
  778. struct ifconf ifc;
  779. int n;
  780. int len;
  781. char *addr;
  782. int family;
  783. struct ifreq *ifr;
  784. ifc.ifc_len = sizeof (buf);
  785. ifc.ifc_buf = buf;
  786. if (ioctl (fd, SIOCGIFCONF, (char *) &ifc) < 0)
  787. LogError ((unsigned char *)"Trouble getting network interface configuration");
  788. for (ifr = ifc.ifc_req
  789. #if defined(BSD44SOCKETS) || defined(CSRG_BASED)
  790. ; (char *)ifr < ifc.ifc_buf + ifc.ifc_len;
  791. ifr = (struct ifreq *)((char *)ifr + sizeof (struct ifreq) +
  792. (ifr->ifr_addr.sa_len > sizeof (ifr->ifr_addr) ?
  793. ifr->ifr_addr.sa_len - sizeof (ifr->ifr_addr) : 0))
  794. #else
  795. , n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++
  796. #endif
  797. )
  798. {
  799. #ifdef DNETCONN
  800. /*
  801. * this is ugly but SIOCGIFCONF returns decnet addresses in
  802. * a different form from other decnet calls
  803. */
  804. if (ifr->ifr_addr.sa_family == AF_DECnet) {
  805. len = sizeof (struct dn_naddr);
  806. addr = (char *)ifr->ifr_addr.sa_data;
  807. family = FamilyDECnet;
  808. } else
  809. #endif
  810. {
  811. if (ConvertAddr ((XdmcpNetaddr) &ifr->ifr_addr, &len, &addr) < 0)
  812. continue;
  813. if (len == 0)
  814. {
  815. Debug ("Skipping zero length address\n");
  816. continue;
  817. }
  818. /*
  819. * don't write out 'localhost' entries, as
  820. * they may conflict with other local entries.
  821. * DefineLocal will always be called to add
  822. * the local entry anyway, so this one can
  823. * be tossed.
  824. */
  825. if (len == 4 &&
  826. addr[0] == 127 && addr[1] == 0 &&
  827. addr[2] == 0 && addr[3] == 1)
  828. {
  829. Debug ("Skipping localhost address\n");
  830. continue;
  831. }
  832. family = FamilyInternet;
  833. }
  834. Debug ("DefineSelf: write network address, length %d\n", len);
  835. writeAddr (family, len, addr, file, auth);
  836. }
  837. }
  838. #else /* SIOCGIFCONF */
  839. /* Define this host for access control. Find all the hosts the OS knows about
  840. * for this fd and add them to the selfhosts list.
  841. */
  842. static void
  843. DefineSelf (int fd, int file, int auth)
  844. {
  845. int n;
  846. int len;
  847. caddr_t addr;
  848. int family;
  849. struct utsname name;
  850. struct hostent *hp;
  851. union {
  852. struct sockaddr sa;
  853. struct sockaddr_in in;
  854. } saddr;
  855. struct sockaddr_in *inetaddr;
  856. /*
  857. * Why not use gethostname()? Well, at least on my system, I've had to
  858. * make an ugly kernel patch to get a name longer than 8 characters, and
  859. * uname() lets me access to the whole string (it smashes release, you
  860. * see), whereas gethostname() kindly truncates it for me.
  861. */
  862. uname(&name);
  863. hp = gethostbyname (name.nodename);
  864. if (hp != NULL) {
  865. saddr.sa.sa_family = hp->h_addrtype;
  866. inetaddr = (struct sockaddr_in *) (&(saddr.sa));
  867. memmove( (char *) &(inetaddr->sin_addr), (char *) hp->h_addr, (int) hp->h_length);
  868. family = ConvertAddr ( &(saddr.sa), &len, &addr);
  869. if ( family >= 0) {
  870. writeAddr (FamilyInternet, sizeof (inetaddr->sin_addr),
  871. (char *) (&inetaddr->sin_addr), file, auth);
  872. }
  873. }
  874. }
  875. #endif /* SIOCGIFCONF else */
  876. #endif /* WINTCP */
  877. static void
  878. setAuthNumber (Xauth *auth, char *name)
  879. {
  880. char *colon;
  881. char *dot, *number;
  882. Debug ("setAuthNumber %s\n", name);
  883. colon = strrchr(name, ':');
  884. if (colon) {
  885. ++colon;
  886. dot = strchr(colon, '.');
  887. if (dot)
  888. auth->number_length = dot - colon;
  889. else
  890. auth->number_length = strlen (colon);
  891. number = malloc (auth->number_length + 1);
  892. if (number) {
  893. strncpy (number, colon, auth->number_length);
  894. number[auth->number_length] = '\0';
  895. } else {
  896. LogOutOfMem (ReadCatalog(
  897. MC_LOG_SET,MC_LOG_NET_CFG,MC_DEF_LOG_NET_CFG));
  898. auth->number_length = 0;
  899. }
  900. auth->number = number;
  901. Debug ("setAuthNumber: %s\n", number);
  902. }
  903. }
  904. static void
  905. writeLocalAuth (FILE *file, Xauth *auth, char *name)
  906. {
  907. int fd;
  908. Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name);
  909. setAuthNumber (auth, name);
  910. #ifdef STREAMSCONN
  911. fd = t_open ("/dev/tcp", O_RDWR, 0);
  912. t_bind(fd, NULL, NULL);
  913. DefineSelf (fd, file, auth);
  914. t_unbind (fd);
  915. t_close (fd);
  916. #endif
  917. #ifdef TCPCONN
  918. fd = socket (AF_INET, SOCK_STREAM, 0);
  919. if(fd != -1) {
  920. DefineSelf (fd, file, auth);
  921. close (fd);
  922. }
  923. #endif
  924. #ifdef DNETCONN
  925. fd = socket (AF_DECnet, SOCK_STREAM, 0);
  926. DefineSelf (fd, file, auth);
  927. close (fd);
  928. #endif
  929. DefineLocal (file, auth);
  930. }
  931. #ifdef XDMCP
  932. static void
  933. writeRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name)
  934. {
  935. int family = FamilyLocal;
  936. char *addr;
  937. Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name);
  938. if (!peer || peerlen < 2)
  939. return;
  940. setAuthNumber (auth, name);
  941. family = ConvertAddr (peer, &peerlen, &addr);
  942. Debug ("writeRemoteAuth: family %d\n", family);
  943. if (family != FamilyLocal)
  944. {
  945. Debug ("writeRemoteAuth: %d, %d, %x\n",
  946. family, peerlen, *(int *)addr);
  947. writeAddr (family, peerlen, addr, file, auth);
  948. }
  949. else
  950. {
  951. writeLocalAuth (file, auth, name);
  952. }
  953. }
  954. #endif /* XDMCP */
  955. void
  956. SetUserAuthorization (struct display *d, struct verify_info *verify)
  957. {
  958. FILE *old, *new;
  959. char home_name[1024], backup_name[1024], new_name[1024];
  960. char home_name_temp[sizeof(home_name)];
  961. char *name;
  962. char *home;
  963. char *envname = 0;
  964. int lockStatus;
  965. Xauth *entry, **auths;
  966. int setenv;
  967. char **setEnv (), *getEnv ();
  968. struct stat statb;
  969. int i;
  970. int magicCookie;
  971. int data_len;
  972. Debug ("SetUserAuthorization\n");
  973. auths = d->authorizations;
  974. if (auths) {
  975. home = getEnv (verify->userEnviron, "HOME");
  976. lockStatus = LOCK_ERROR;
  977. if (home) {
  978. snprintf(home_name, sizeof(home_name), "%s", home);
  979. if (home[strlen(home) - 1] != '/') {
  980. snprintf(home_name_temp, sizeof(home_name_temp), "%s/", home_name);
  981. strcpy(home_name, home_name_temp);
  982. }
  983. snprintf(home_name_temp, sizeof(home_name_temp), "%s.Xauthority", home_name);
  984. strcpy(home_name, home_name_temp);
  985. Debug ("XauLockAuth %s\n", home_name);
  986. lockStatus = XauLockAuth (home_name, 1, 2, 10);
  987. Debug ("Lock is %d\n", lockStatus);
  988. if (lockStatus == LOCK_SUCCESS) {
  989. if (openFiles (home_name, new_name, &old, &new)) {
  990. name = home_name;
  991. setenv = 0;
  992. } else {
  993. Debug ("openFiles failed\n");
  994. XauUnlockAuth (home_name);
  995. lockStatus = LOCK_ERROR;
  996. }
  997. }
  998. }
  999. if (lockStatus != LOCK_SUCCESS) {
  1000. sprintf (backup_name, "%s/.XauthXXXXXX", d->userAuthDir);
  1001. (void) mktemp (backup_name);
  1002. Debug ("XauLockAuth %s\n", backup_name);
  1003. lockStatus = XauLockAuth (backup_name, 1, 2, 10);
  1004. Debug ("backup lock is %d\n", lockStatus);
  1005. if (lockStatus == LOCK_SUCCESS) {
  1006. if (openFiles (backup_name, new_name, &old, &new)) {
  1007. name = backup_name;
  1008. setenv = 1;
  1009. } else {
  1010. XauUnlockAuth (backup_name);
  1011. lockStatus = LOCK_ERROR;
  1012. }
  1013. }
  1014. /*
  1015. * Won't be using this file so unlock it.
  1016. */
  1017. XauUnlockAuth (home_name);
  1018. }
  1019. if (lockStatus != LOCK_SUCCESS) {
  1020. Debug ("can't lock auth file %s or backup %s\n",
  1021. home_name, backup_name);
  1022. LogError (ReadCatalog
  1023. (MC_LOG_SET,MC_LOG_LCK_AUTH,MC_DEF_LOG_LCK_AUTH),
  1024. home_name, backup_name);
  1025. return;
  1026. }
  1027. initAddrs ();
  1028. doWrite = 1;
  1029. Debug ("%d authorization protocols for %s\n", d->authNum, d->name);
  1030. /*
  1031. * Write MIT-MAGIC-COOKIE-1 authorization first, so that
  1032. * R4 clients which only knew that, and used the first
  1033. * matching entry will continue to function
  1034. */
  1035. magicCookie = -1;
  1036. for (i = 0; i < d->authNum; i++)
  1037. {
  1038. if (auths[i]->name_length == 18 &&
  1039. !strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18))
  1040. {
  1041. magicCookie = i;
  1042. if (d->displayType.location == Local)
  1043. writeLocalAuth (new, auths[i], d->name);
  1044. #ifdef XDMCP
  1045. else
  1046. writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
  1047. #endif
  1048. break;
  1049. }
  1050. }
  1051. /* now write other authorizations */
  1052. for (i = 0; i < d->authNum; i++)
  1053. {
  1054. Debug("SetUserAuthorization: checking authorization # %d\n", i+1);
  1055. if (i != magicCookie)
  1056. {
  1057. data_len = auths[i]->data_length;
  1058. /* client will just use default Kerberos cache, so don't
  1059. * even write cache info into the authority file.
  1060. */
  1061. if (auths[i]->name_length == 14 &&
  1062. !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14))
  1063. auths[i]->data_length = 0;
  1064. if (d->displayType.location == Local)
  1065. writeLocalAuth (new, auths[i], d->name);
  1066. #ifdef XDMCP
  1067. else
  1068. writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
  1069. #endif
  1070. auths[i]->data_length = data_len;
  1071. }
  1072. }
  1073. Debug ("SetUserAuthorization: old = %x\n", old);
  1074. if (old) {
  1075. if (fstat (fileno (old), &statb) != -1)
  1076. chmod (new_name, (int) (statb.st_mode & 0777));
  1077. /*SUPPRESS 560*/
  1078. while (entry = XauReadAuth (old)) {
  1079. if (!checkEntry (entry))
  1080. {
  1081. Debug ("Writing an entry\n");
  1082. writeAuth (new, entry);
  1083. }
  1084. XauDisposeAuth (entry);
  1085. }
  1086. fclose (old);
  1087. }
  1088. doneAddrs ();
  1089. fclose (new);
  1090. Debug ("SetUserAuthorization: name = %s\n", name);
  1091. Debug ("SetUserAuthorization: new_name = %s\n", new_name);
  1092. Debug ("SetUserAuthorization: unlink(%s)\n", name);
  1093. if (unlink (name) == -1)
  1094. Debug ("SetUserAuthorization: unlink(%s) failed!\n", name);
  1095. envname = name;
  1096. if (link (new_name, name) == -1) {
  1097. Debug ("link failed %s %s\n", new_name, name);
  1098. LogError (
  1099. ReadCatalog(MC_LOG_SET,MC_LOG_NOT_AUTH,MC_DEF_LOG_NOT_AUTH));
  1100. setenv = 1;
  1101. envname = new_name;
  1102. } else {
  1103. Debug ("SetUserAuthorization: link(%s,%s) OK\n", new_name, name);
  1104. Debug ("SetUserAuthorization: unlink(%s)\n", new_name);
  1105. unlink (new_name);
  1106. }
  1107. if (setenv) {
  1108. Debug ("SetUserAuthorization: setenv(XAUTHORITY=%s)\n", envname);
  1109. verify->userEnviron = setEnv (verify->userEnviron,
  1110. "XAUTHORITY", envname);
  1111. verify->systemEnviron = setEnv (verify->systemEnviron,
  1112. "XAUTHORITY", envname);
  1113. }
  1114. Debug ("SetUserAuthorization: XauUnLockAuth(%s)\n", name);
  1115. XauUnlockAuth (name);
  1116. Debug ("SetUserAuthorization: envname = %s\n", envname);
  1117. if (envname) {
  1118. #ifdef NGROUPS
  1119. Debug ("SetUserAuthorization: chown(%s,%d,%d)\n",
  1120. envname, verify->uid, verify->groups[0]);
  1121. if(-1 == chown (envname, verify->uid, verify->groups[0])) {
  1122. perror(strerror(errno));
  1123. }
  1124. #else
  1125. Debug ("SetUserAuthorization: chown(%s,%d,%d)\n",
  1126. envname, verify->uid, verify->gid);
  1127. if(-1 == chown (envname, verify->uid, verify->gid)) {
  1128. perror(strerror(errno));
  1129. }
  1130. #endif /* NGROUPS */
  1131. }
  1132. }
  1133. Debug ("done SetUserAuthorization\n");
  1134. }
  1135. void
  1136. RemoveUserAuthorization (struct display *d, struct verify_info *verify)
  1137. {
  1138. char *home;
  1139. Xauth **auths, *entry;
  1140. char name[1024], new_name[1024];
  1141. char name_temp[sizeof(name)];
  1142. int lockStatus;
  1143. FILE *old, *new;
  1144. struct stat statb;
  1145. int i;
  1146. char *getEnv ();
  1147. if (!(auths = d->authorizations))
  1148. return;
  1149. home = getEnv (verify->userEnviron, "HOME");
  1150. if (!home)
  1151. return;
  1152. Debug ("RemoveUserAuthorization\n");
  1153. snprintf(name, sizeof(name), "%s", home);
  1154. if (home[strlen(home) - 1] != '/') {
  1155. snprintf(name_temp, sizeof(name_temp), "%s/", name);
  1156. strcpy(name, name_temp);
  1157. }
  1158. snprintf(name_temp, sizeof(name_temp), "%s.Xauthority", name);
  1159. strcpy(name, name_temp);
  1160. Debug ("XauLockAuth %s\n", name);
  1161. lockStatus = XauLockAuth (name, 1, 2, 10);
  1162. Debug ("Lock is %d\n", lockStatus);
  1163. if (lockStatus != LOCK_SUCCESS)
  1164. return;
  1165. if (openFiles (name, new_name, &old, &new))
  1166. {
  1167. initAddrs ();
  1168. doWrite = 0;
  1169. for (i = 0; i < d->authNum; i++)
  1170. {
  1171. if (d->displayType.location == Local)
  1172. writeLocalAuth (new, auths[i], d->name);
  1173. #ifdef XDMCP
  1174. else
  1175. writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
  1176. #endif
  1177. }
  1178. doWrite = 1;
  1179. if (old) {
  1180. if (fstat (fileno (old), &statb) != -1)
  1181. chmod (new_name, (int) (statb.st_mode & 0777));
  1182. /*SUPPRESS 560*/
  1183. while (entry = XauReadAuth (old)) {
  1184. if (!checkEntry (entry))
  1185. {
  1186. Debug ("Writing an entry\n");
  1187. writeAuth (new, entry);
  1188. }
  1189. XauDisposeAuth (entry);
  1190. }
  1191. fclose (old);
  1192. }
  1193. doneAddrs ();
  1194. fclose (new);
  1195. if (unlink (name) == -1)
  1196. Debug ("unlink %s failed\n", name);
  1197. if (link (new_name, name) == -1) {
  1198. Debug ("link failed %s %s\n", new_name, name);
  1199. LogError (
  1200. ReadCatalog(MC_LOG_SET,MC_LOG_NOT_AUTH,MC_DEF_LOG_NOT_AUTH));
  1201. } else {
  1202. Debug ("new is in place, go for it!\n");
  1203. unlink (new_name);
  1204. }
  1205. }
  1206. XauUnlockAuth (name);
  1207. }