2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
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:
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
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.
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
30 #include <X11/Xtrans/Xtrans.h>
31 #include <X11/Xtrans/Xtransint.h>
35 #include "dixstruct.h"
37 static DevPrivateKeyRec OSAuditPrivKeyRec
;
38 #define OSAuditPrivKey (&OSAuditPrivKeyRec)
40 #define GetOSAuditClient(pClient) \
41 ((OSAuditClientPrivatePtr) dixLookupPrivate(&(pClient)->devPrivates, OSAuditPrivKey))
43 #ifdef HAVE_LIBBSM /* Solaris auditing implementation */
46 #include <bsm/adt_event.h>
49 # define OS_AUDIT_IMPLEMENTED
52 adt_session_data_t
*ah
; /* audit handle */
53 ClientState prevState
;
54 } OSAuditClientPrivateRec
, *OSAuditClientPrivatePtr
;
57 OSAuditClientInit (ClientPtr pClient
)
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 */
65 OSAuditClientPrivatePtr priv
= GetOSAuditClient(pClient
);
69 /* reset privs back to root */
71 ErrorF("OSAuditClientInit: seteuid(0): %s\n", strerror(errno
));
76 if (adt_start_session(&ah
, NULL
, 0) != 0) {
77 ErrorF("OSAuditClientInit: adt_start_session: %s\n", strerror(errno
));
81 if (pClient
->osPrivate
== NULL
) {
82 ErrorF("OSAuditClientInit: NULL osPrivate: %s\n", strerror(errno
));
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 ErrorF("OSAuditClientInit: adt_set_from_ucred: %s\n",
94 if (adt_set_user(ah
, ADT_NO_ATTRIB
, ADT_NO_ATTRIB
, ADT_NO_ATTRIB
,
95 ADT_NO_ATTRIB
, NULL
, ADT_NEW
) != 0) {
96 ErrorF("OSAuditClientInit: adt_set_user: %s\n", strerror(errno
));
104 /* set privs back to user */
105 if (seteuid(saveid
) < 0) {
106 ErrorF("OSAuditClientInit: seteuid(saveid): %s\n", strerror(errno
));
113 OSAudit (ClientPtr pClient
, int event_id
, int status
, int reason
)
115 adt_event_data_t
*event
; /* event handle */
116 XtransConnInfo ci
; /* peer's connection info */
117 int peer
; /* peer's file descriptor */
120 OSAuditClientPrivatePtr priv
= GetOSAuditClient(pClient
);
122 if (priv
->ah
== NULL
) {
123 ErrorF("OSAudit: NULL adt_session_data: %s\n", strerror(errno
));
127 if ((event
= adt_alloc_event(priv
->ah
, event_id
)) == NULL
) {
128 ErrorF("OSAudit: adt_set_from_ucred: %s\n", strerror(errno
));
135 if (pClient
->osPrivate
!= NULL
) {
136 ci
= ((OsCommPtr
)pClient
->osPrivate
)->trans_conn
;
137 peer
= _XSERVTransGetConnectionNumber(ci
);
141 event
->adt_xconnect
.client
= pClient
->index
;
142 event
->adt_xconnect
.peer
= peer
;
144 case ADT_xdisconnect
:
145 event
->adt_xdisconnect
.client
= pClient
->index
;
148 ErrorF("OSAudit: unknown event_id: %s\n", strerror(errno
));
153 /* reset privs back to root */
154 if (seteuid(0) < 0) {
155 ErrorF("OSAuditClientInit: seteuid(0): %s\n", strerror(errno
));
160 if (adt_put_event(event
, status
, reason
) != 0) {
161 ErrorF("OSAudit: adt_put_event: %s\n", strerror(errno
));
165 /* set privs back to user */
166 if (seteuid(saveid
) < 0) {
167 ErrorF("OSAuditClientInit: seteuid(saveid): %s\n", strerror(errno
));
171 adt_free_event(event
);
174 /* Called when new client connects or existing client disconnects */
176 OSAuditClientStateChange(CallbackListPtr
*pcbl
, void *nulldata
, void *calldata
)
178 NewClientInfoRec
*pci
= (NewClientInfoRec
*)calldata
;
179 ClientPtr pClient
= pci
->client
;
180 OSAuditClientPrivatePtr priv
= GetOSAuditClient(pClient
);
182 switch (pClient
->clientState
) {
184 case ClientStateInitial
: /* client attempting to connect */
185 OSAuditClientInit(pClient
);
188 case ClientStateRunning
: /* connection accepted */
189 OSAudit (pClient
, ADT_xconnect
, ADT_SUCCESS
, ADT_SUCCESS
);
192 case ClientStateGone
: /* connection terminating */
193 if (priv
->prevState
== ClientStateInitial
) /* was never accepted */
194 OSAudit (pClient
, ADT_xconnect
, ADT_FAILURE
, EACCES
);
195 else /* successful connection that ran for a while */
196 OSAudit (pClient
, ADT_xdisconnect
, ADT_SUCCESS
, ADT_SUCCESS
);
197 adt_end_session(priv
->ah
);
202 return; /* skip over setting prevState to an unknown state */
205 priv
->prevState
= pClient
->clientState
;
207 #endif /* ADT_xconnect */
208 #endif /* HAVE_LIBBSM -- Solaris auditing implementation */
210 /* Generic code to initialize all OS auditing implementations */
214 #ifdef OS_AUDIT_IMPLEMENTED
215 /* Reserve room in the client privates for the audit data */
216 if (!dixRegisterPrivateKey(&OSAuditPrivKeyRec
, PRIVATE_CLIENT
,
217 sizeof(OSAuditClientPrivateRec
)))
218 FatalError("could not allocate OSAuditPrivKey\n");
220 /* Register callback to be called on every client connect & disconnect */
221 if (!AddCallback(&ClientStateCallback
, OSAuditClientStateChange
, NULL
))
222 FatalError("could not register OSAuditClientStateChange callback\n");
224 /* nothing implemented for this OS */