6 #include <architecture/byte_order.h>
7 #include <security_cdsa_utilities/cssmdb.h>
8 #include "SharedMemoryClient.h"
10 #include <security_utilities/crc.h>
11 #include <securityd_client/ssnotify.h>
12 #include <Security/SecKeychain.h>
14 using namespace Security
;
16 //=================================================================================
18 //=================================================================================
20 static std::string
unixerrorstr(int errnum
) {
23 // might return ERANGE
24 /* int rx = */ strerror_r(errnum
, buf
, sizeof(buf
));
26 errstr
+= "(" + to_string(errnum
) + ")";
30 SharedMemoryClient::SharedMemoryClient (const char* segmentName
, SegmentOffsetType segmentSize
, uid_t uid
)
32 StLock
<Mutex
> _(mMutex
);
34 mSegmentName
= segmentName
;
35 mSegmentSize
= segmentSize
;
36 mSegment
= (u_int8_t
*) MAP_FAILED
;
37 mDataArea
= mDataPtr
= 0;
40 secdebug("MDSPRIVACY","[%03d] creating SharedMemoryClient with segmentName %s, size: %d", mUID
, segmentName
, segmentSize
);
42 if (segmentSize
< sizeof(u_int32_t
))
46 int segmentDescriptor
;
48 std::string
name(SharedMemoryCommon::SharedMemoryFilePath(mSegmentName
.c_str(), mUID
));
50 // make a connection to the shared memory block
51 segmentDescriptor
= open (name
.c_str(), O_RDONLY
, S_IROTH
);
52 if (segmentDescriptor
< 0) // error on opening the shared memory segment?
54 secdebug("MDSPRIVACY","[%03d] SharedMemoryClient open of %s failed: %s", mUID
, name
.c_str(), unixerrorstr(errno
).c_str());
55 // CssmError::throwMe (CSSM_ERRCODE_INTERNAL_ERROR);
60 // check that the file size is large enough to support operations
61 struct stat statResult
= {};
62 int result
= fstat(segmentDescriptor
, &statResult
);
64 secdebug("MDSPRIVACY","[%03d] SharedMemoryClient fstat failed: %d/%s", mUID
, result
, unixerrorstr(errno
).c_str());
65 UnixError::throwMe(errno
);
68 off_t sz
= statResult
.st_size
;
69 if(sz
< sizeof(SegmentOffsetType
)) {
70 close(segmentDescriptor
);
74 if(sz
> 4*segmentSize
) {
75 // File is too ridiculously large. Quit.
76 close(segmentDescriptor
);
80 // map the segment into place
81 mSegment
= (u_int8_t
*) mmap (NULL
, segmentSize
, PROT_READ
, MAP_SHARED
, segmentDescriptor
, 0);
82 close (segmentDescriptor
);
84 if (mSegment
== MAP_FAILED
)
86 secdebug("MDSPRIVACY","[%03d] SharedMemoryClient mmap failed: %d", mUID
, errno
);
90 mDataArea
= mSegment
+ sizeof (SegmentOffsetType
);
91 mDataMax
= mSegment
+ sz
;
92 mDataPtr
= mDataArea
+ GetProducerCount ();
97 SharedMemoryClient::~SharedMemoryClient ()
99 if (!uninitialized()) {
100 StLock
<Mutex
> _(mMutex
);
101 munmap (mSegment
, mSegmentSize
);
106 SegmentOffsetType
SharedMemoryClient::GetProducerCount ()
108 if (uninitialized()) {
109 secdebug("MDSPRIVACY","[%03d] SharedMemoryClient::GetProducerCount uninitialized", mUID
);
110 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
112 if( ((u_int8_t
*) (((u_int32_t
*) mSegment
) + 1)) > mDataMax
) {
113 // Check we can actually read this u_int32_t
114 secdebug("MDSPRIVACY","[%03d] SharedMemoryClient::GetProducerCount uint > mDataMax", mUID
);
115 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
118 SegmentOffsetType offset
= OSSwapBigToHostInt32 (*(u_int32_t
*) mSegment
);
119 if (&mSegment
[offset
] >= mDataMax
) {
120 secdebug("MDSPRIVACY","[%03d] SharedMemoryClient::GetProducerCount offset > mDataMax", mUID
);
121 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
127 void SharedMemoryClient::ReadData (void* buffer
, SegmentOffsetType length
)
129 if (uninitialized()) {
130 secdebug("MDSPRIVACY","[%03d] ReadData mSegment fail uninitialized: %p", mUID
, mSegment
);
131 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
134 u_int8_t
* bptr
= (u_int8_t
*) buffer
;
136 SegmentOffsetType bytesToEnd
= (SegmentOffsetType
)(mDataMax
- mDataPtr
);
138 // figure out how many bytes we can read
139 SegmentOffsetType bytesToRead
= (length
<= bytesToEnd
) ? length
: bytesToEnd
;
141 // move the first part of the data
142 memcpy (bptr
, mDataPtr
, bytesToRead
);
145 // see if we have anything else to read
146 mDataPtr
+= bytesToRead
;
148 length
-= bytesToRead
;
151 mDataPtr
= mDataArea
;
152 memcpy(bptr
, mDataPtr
, length
);
159 SegmentOffsetType
SharedMemoryClient::ReadOffset()
161 SegmentOffsetType offset
;
162 ReadData(&offset
, sizeof(SegmentOffsetType
));
163 offset
= OSSwapBigToHostInt32 (offset
);
169 bool SharedMemoryClient::ReadMessage (void* message
, SegmentOffsetType
&length
, UnavailableReason
&ur
)
171 StLock
<Mutex
> _(mMutex
);
173 if (uninitialized()) {
174 secdebug("MDSPRIVACY","[%03d] ReadMessage mSegment fail uninitialized: %p", mUID
, mSegment
);
175 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
180 size_t offset
= mDataPtr
- mDataArea
;
181 if (offset
== GetProducerCount())
183 secdebug("MDSPRIVACY","[%03d] ReadMessage GetProducerCount()", mUID
);
188 // get the length of the message in the buffer
189 length
= ReadOffset();
191 // we have the possibility that data is correct, figure out where the data is actually located
192 // get the length of the message stored there
193 if (length
== 0 || length
>= kPoolAvailableForData
)
195 secdebug("MDSPRIVACY","[%03d] ReadMessage length error: %d", mUID
, length
);
196 ur
= (length
== 0) ? kURNoMessage
: kURBufferCorrupt
;
198 // something's gone wrong, reset.
199 mDataPtr
= mDataArea
+ GetProducerCount ();
204 SegmentOffsetType crc
= ReadOffset();
206 // read the data into the buffer
207 ReadData (message
, length
);
210 SegmentOffsetType crc2
= CalculateCRC((u_int8_t
*) message
, length
);
213 ur
= kURBufferCorrupt
;
214 mDataPtr
= mDataArea
+ GetProducerCount ();
221 //=================================================================================
222 // SharedMemoryCommon
223 //=================================================================================
225 std::string
SharedMemoryCommon::SharedMemoryFilePath(const char *segmentName
, uid_t uid
) {
227 uid
= SharedMemoryCommon::fixUID(uid
);
228 path
= SharedMemoryCommon::kMDSMessagesDirectory
; // i.e. /private/var/db/mds/messages/
230 path
+= std::to_string(uid
) + "/"; // e.g. /private/var/db/mds/messages/501/
233 path
+= SharedMemoryCommon::kUserPrefix
; // e.g. /var/db/mds/messages/se_
234 path
+= segmentName
; // e.g. /var/db/mds/messages/501/se_SecurityMessages
238 std::string
SharedMemoryCommon::notificationDescription(int domain
, int event
) {
239 string domainstr
, eventstr
;
242 case Security::SecurityServer::kNotificationDomainAll
: domainstr
= "all"; break;
243 case Security::SecurityServer::kNotificationDomainDatabase
: domainstr
= "database"; break;
244 case Security::SecurityServer::kNotificationDomainPCSC
: domainstr
= "pcsc"; break;
245 case Security::SecurityServer::kNotificationDomainCDSA
: domainstr
= "CDSA"; break;
247 domainstr
= "unknown";
252 case kSecLockEvent
: eventstr
= "lock"; break;
253 case kSecUnlockEvent
: eventstr
= "unlock"; break;
254 case kSecAddEvent
: eventstr
= "add"; break;
255 case kSecDeleteEvent
: eventstr
= "delete"; break;
256 case kSecUpdateEvent
: eventstr
= "update"; break;
257 case kSecPasswordChangedEvent
: eventstr
= "passwordChange"; break;
258 case kSecDefaultChangedEvent
: eventstr
= "defaultChange"; break;
259 case kSecDataAccessEvent
: eventstr
= "dataAccess"; break;
260 case kSecKeychainListChangedEvent
: eventstr
= "listChange"; break;
261 case kSecTrustSettingsChangedEvent
: eventstr
= "trustSettings"; break;
263 domainstr
= "unknown";
267 return "Domain: " + domainstr
+ ", Event: " + eventstr
;