open-src/xserver/xorg/sun-src/os/osaudit.c
changeset 1149 e852f51b09cd
equal deleted inserted replaced
1148:bf06d87c78ae 1149:e852f51b09cd
       
     1 /*
       
     2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  *
       
     4  * Permission is hereby granted, free of charge, to any person obtaining a
       
     5  * copy of this software and associated documentation files (the "Software"),
       
     6  * to deal in the Software without restriction, including without limitation
       
     7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       
     8  * and/or sell copies of the Software, and to permit persons to whom the
       
     9  * Software is furnished to do so, subject to the following conditions:
       
    10  *
       
    11  * The above copyright notice and this permission notice (including the next
       
    12  * paragraph) shall be included in all copies or substantial portions of the
       
    13  * Software.
       
    14  *
       
    15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
       
    18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
       
    20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
       
    21  * DEALINGS IN THE SOFTWARE.
       
    22  */
       
    23 
       
    24 #ifdef HAVE_DIX_CONFIG_H
       
    25 #include <dix-config.h>
       
    26 #endif
       
    27 
       
    28 #define XSERV_t
       
    29 #define TRANS_SERVER
       
    30 #include <X11/Xtrans/Xtrans.h>
       
    31 #include <X11/Xtrans/Xtransint.h>
       
    32 
       
    33 #include "misc.h"
       
    34 #include "osdep.h"
       
    35 #include "dixstruct.h"
       
    36 
       
    37 static DevPrivateKeyRec OSAuditPrivKeyRec;
       
    38 #define OSAuditPrivKey (&OSAuditPrivKeyRec)
       
    39 
       
    40 #define GetOSAuditClient(pClient)    \
       
    41   ((OSAuditClientPrivatePtr) dixLookupPrivate(&(pClient)->devPrivates, OSAuditPrivKey))
       
    42 
       
    43 #ifdef HAVE_LIBBSM	/* Solaris auditing implementation */
       
    44 #include <ucred.h>
       
    45 #include <bsm/adt.h>
       
    46 #include <bsm/adt_event.h>
       
    47 
       
    48 #ifdef ADT_xconnect
       
    49 # define OS_AUDIT_IMPLEMENTED
       
    50 
       
    51 typedef struct {
       
    52     adt_session_data_t	*ah;		/* audit handle */
       
    53     ClientState		 prevState;
       
    54 } OSAuditClientPrivateRec, *OSAuditClientPrivatePtr;
       
    55 
       
    56 static void
       
    57 OSAuditClientInit (ClientPtr pClient)
       
    58 {
       
    59     adt_session_data_t	*ah;		/* audit handle */
       
    60     ucred_t		*uc = NULL;	/* peer's ucred */
       
    61     XtransConnInfo	 ci;		/* peer's connection info */
       
    62     int			 peer;		/* peer's file descriptor */
       
    63     int			 saveid;
       
    64 
       
    65     OSAuditClientPrivatePtr	 priv = GetOSAuditClient(pClient);
       
    66 
       
    67     saveid = geteuid();
       
    68     if (saveid != 0) {
       
    69 	/* reset privs back to root */
       
    70         if (seteuid(0) < 0) {
       
    71 	    Error("OSAuditClientInit: seteuid(0)");
       
    72 	    saveid = 0;
       
    73 	}
       
    74     }
       
    75     
       
    76     if (adt_start_session(&ah, NULL, 0) != 0) {
       
    77 	Error("OSAuditClientInit: adt_start_session");
       
    78 	goto end;
       
    79     }
       
    80 
       
    81     if (pClient->osPrivate == NULL) {
       
    82 	Error("OSAuditClientInit: NULL osPrivate");
       
    83 	goto end;
       
    84     }
       
    85     ci = ((OsCommPtr)pClient->osPrivate)->trans_conn;
       
    86     peer = _XSERVTransGetConnectionNumber(ci);
       
    87     if (getpeerucred(peer, &uc) == 0) {
       
    88 	if (adt_set_from_ucred(ah, uc, ADT_NEW) != 0) {
       
    89 	    Error("OSAuditClientInit: adt_set_from_ucred");
       
    90 	}
       
    91 	ucred_free(uc);
       
    92     } else {
       
    93 	if (adt_set_user(ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB, ADT_NO_ATTRIB,
       
    94 			 ADT_NO_ATTRIB, NULL, ADT_NEW) != 0) {
       
    95 	    Error("OSAuditClientInit: adt_set_user");
       
    96 	}
       
    97     }
       
    98 
       
    99     priv->ah = ah;
       
   100 
       
   101   end:
       
   102     if (saveid != 0) {
       
   103 	/* set privs back to user */
       
   104         if (seteuid(saveid) < 0) {
       
   105 	    Error("OSAuditClientInit: seteuid(saveid)");
       
   106 	}
       
   107     }
       
   108 
       
   109 }
       
   110 
       
   111 static void
       
   112 OSAudit (ClientPtr pClient, int event_id, int status, int reason)
       
   113 {
       
   114     adt_event_data_t	*event;		/* event handle */
       
   115     XtransConnInfo	 ci;		/* peer's connection info */
       
   116     int			 peer;		/* peer's file descriptor */
       
   117     int			 saveid;
       
   118 
       
   119     OSAuditClientPrivatePtr	 priv = GetOSAuditClient(pClient);
       
   120 
       
   121     if (priv->ah == NULL) {
       
   122 	Error("OSAudit: NULL adt_session_data");
       
   123 	return;
       
   124     }
       
   125 
       
   126     if ((event = adt_alloc_event(priv->ah, event_id)) == NULL) {
       
   127 	Error("OSAudit: adt_set_from_ucred");
       
   128 	return;
       
   129     }
       
   130 
       
   131     /* fill in event */
       
   132     switch (event_id) {
       
   133     case ADT_xconnect:
       
   134 	if (pClient->osPrivate != NULL) {
       
   135 	    ci = ((OsCommPtr)pClient->osPrivate)->trans_conn;
       
   136 	    peer = _XSERVTransGetConnectionNumber(ci);
       
   137 	} else {
       
   138 	    peer = -1;
       
   139 	}
       
   140 	event->adt_xconnect.client = pClient->index;
       
   141 	event->adt_xconnect.peer = peer;
       
   142 	break;
       
   143     case ADT_xdisconnect:
       
   144 	event->adt_xdisconnect.client = pClient->index;
       
   145 	break;
       
   146     default:
       
   147 	Error("OSAudit: unknown event_id");
       
   148     }
       
   149 
       
   150     saveid = geteuid();
       
   151     if (saveid != 0) {
       
   152 	/* reset privs back to root */
       
   153         if (seteuid(0) < 0) {
       
   154 	    Error("OSAuditClientInit: seteuid(0)");
       
   155 	    saveid = 0;
       
   156 	}
       
   157     }
       
   158     
       
   159     if (adt_put_event(event, status, reason) != 0) {
       
   160 	Error("OSAudit: adt_put_event");
       
   161     }
       
   162 
       
   163     if (saveid != 0) {
       
   164 	/* set privs back to user */
       
   165         if (seteuid(saveid) < 0) {
       
   166 	    Error("OSAuditClientInit: seteuid(saveid)");
       
   167 	}
       
   168     }    
       
   169     
       
   170     adt_free_event(event);
       
   171 }
       
   172 
       
   173 /* Called when new client connects or existing client disconnects */
       
   174 static void
       
   175 OSAuditClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
       
   176 {
       
   177     NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
       
   178     ClientPtr pClient = pci->client;
       
   179     OSAuditClientPrivatePtr	 priv = GetOSAuditClient(pClient);
       
   180 
       
   181     switch (pClient->clientState) {
       
   182 
       
   183     case ClientStateInitial:  /* client attempting to connect */
       
   184 	OSAuditClientInit(pClient);
       
   185 	break;
       
   186 
       
   187     case ClientStateRunning:  /* connection accepted */
       
   188 	OSAudit (pClient, ADT_xconnect, ADT_SUCCESS, ADT_SUCCESS);
       
   189 	break;
       
   190 
       
   191     case ClientStateGone:     /* connection terminating */
       
   192 	if (priv->prevState == ClientStateInitial) /* was never accepted */
       
   193 	    OSAudit (pClient, ADT_xconnect, ADT_FAILURE, EACCES);
       
   194 	else	/* successful connection that ran for a while */
       
   195 	    OSAudit (pClient, ADT_xdisconnect, ADT_SUCCESS, ADT_SUCCESS);
       
   196 	adt_end_session(priv->ah);
       
   197 	priv->ah = NULL;
       
   198 	break;
       
   199 
       
   200     default:
       
   201 	return; /* skip over setting prevState to an unknown state */
       
   202     }
       
   203 
       
   204     priv->prevState = pClient->clientState;
       
   205 }
       
   206 #endif /* ADT_xconnect */
       
   207 #endif /* HAVE_LIBBSM -- Solaris auditing implementation */
       
   208 
       
   209 /* Generic code to initialize all OS auditing implementations */
       
   210 void
       
   211 OSAuditInit(void)
       
   212 {
       
   213 #ifdef OS_AUDIT_IMPLEMENTED
       
   214     /* Reserve room in the client privates for the audit data */
       
   215     if (!dixRegisterPrivateKey(&OSAuditPrivKeyRec, PRIVATE_CLIENT,
       
   216 			       sizeof(OSAuditClientPrivateRec)))
       
   217 	FatalError("could not allocate OSAuditPrivKey\n");
       
   218 
       
   219     /* Register callback to be called on every client connect & disconnect */
       
   220     if (!AddCallback(&ClientStateCallback, OSAuditClientStateChange, NULL))
       
   221 	FatalError("could not register OSAuditClientStateChange callback\n");
       
   222 #else
       
   223 /* nothing implemented for this OS */
       
   224     return;
       
   225 #endif
       
   226 }