Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

lpcpriv.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 lpcpriv.c 00008 00009 Abstract: 00010 00011 Local Inter-Process Communication priviledged procedures that implement 00012 client impersonation. 00013 00014 Author: 00015 00016 Steve Wood (stevewo) 15-Nov-1989 00017 00018 00019 Revision History: 00020 00021 --*/ 00022 00023 #include "lpcp.h" 00024 00025 #ifdef ALLOC_PRAGMA 00026 #pragma alloc_text(PAGE,LpcpFreePortClientSecurity) 00027 #pragma alloc_text(PAGE,NtImpersonateClientOfPort) 00028 #endif 00029 00030 00031 NTSTATUS 00032 NtImpersonateClientOfPort ( 00033 IN HANDLE PortHandle, 00034 IN PPORT_MESSAGE Message 00035 ) 00036 00037 /*++ 00038 00039 Routine Description: 00040 00041 This procedure is used by the server thread to temporarily acquire the 00042 identifier set of a client thread. 00043 00044 This service establishes an impersonation token for the calling thread. 00045 The impersonation token corresponds to the context provided by the port 00046 client. The client must currently be waiting for a reply to the 00047 specified message. 00048 00049 This service returns an error status code if the client thread is not 00050 waiting for a reply to the message. The security quality of service 00051 parameters specified by the client upon connection dictate what use the 00052 server will have of the client's security context. 00053 00054 For complicated or extended impersonation needs, the server may open a 00055 copy of the client's token (using NtOpenThreadToken()). This must be 00056 done while impersonating the client. 00057 00058 Arguments: 00059 00060 PortHandle - Specifies the handle of the communication port that the 00061 message was received from. 00062 00063 Message - Specifies an address of a message that was received from the 00064 client that is to be impersonated. The ClientId field of the message 00065 identifies the client thread that is to be impersonated. The client 00066 thread must be waiting for a reply to the message in order to 00067 impersonate the client. 00068 00069 Return Value: 00070 00071 NTSTATUS - Status code that indicates whether or not the operation was 00072 successful. 00073 00074 --*/ 00075 00076 { 00077 PLPCP_PORT_OBJECT PortObject; 00078 PLPCP_PORT_OBJECT ConnectedPort; 00079 KPROCESSOR_MODE PreviousMode; 00080 NTSTATUS Status; 00081 PETHREAD ClientThread; 00082 CLIENT_ID CapturedClientId; 00083 ULONG CapturedMessageId; 00084 SECURITY_CLIENT_CONTEXT DynamicSecurity; 00085 PLIST_ENTRY Next, Head; 00086 PETHREAD ThreadWaitingForReply; 00087 00088 PAGED_CODE(); 00089 00090 // 00091 // Get previous processor mode and probe output arguments if necessary. 00092 // 00093 00094 PreviousMode = KeGetPreviousMode(); 00095 00096 if (PreviousMode != KernelMode) { 00097 00098 try { 00099 00100 ProbeForRead( Message, sizeof( PORT_MESSAGE ), sizeof( ULONG )); 00101 00102 CapturedClientId = Message->ClientId; 00103 CapturedMessageId = Message->MessageId; 00104 00105 } except( EXCEPTION_EXECUTE_HANDLER ) { 00106 00107 return( GetExceptionCode() ); 00108 } 00109 00110 } else { 00111 00112 CapturedClientId = Message->ClientId; 00113 CapturedMessageId = Message->MessageId; 00114 } 00115 00116 // 00117 // Reference the communication port object by handle. Return status if 00118 // unsuccessful. 00119 // 00120 00121 Status = LpcpReferencePortObject( PortHandle, 0, 00122 PreviousMode, &PortObject ); 00123 if (!NT_SUCCESS( Status )) { 00124 00125 return( Status ); 00126 } 00127 00128 // 00129 // It is an error to try this on any port other than a server 00130 // communication port 00131 // 00132 00133 if ((PortObject->Flags & PORT_TYPE) != SERVER_COMMUNICATION_PORT) { 00134 00135 ObDereferenceObject( PortObject ); 00136 00137 return( STATUS_INVALID_PORT_HANDLE ); 00138 } 00139 00140 // 00141 // Translate the ClientId from the connection request into a 00142 // thread pointer. This is a referenced pointer to keep the thread 00143 // from evaporating out from under us. 00144 // 00145 00146 Status = PsLookupProcessThreadByCid( &CapturedClientId, 00147 NULL, 00148 &ClientThread ); 00149 00150 if (!NT_SUCCESS( Status )) { 00151 00152 ObDereferenceObject( PortObject ); 00153 00154 return( Status ); 00155 } 00156 00157 // 00158 // Acquire the mutex that guards the LpcReplyMessage field of 00159 // the thread and get the pointer to the message that the thread 00160 // is waiting for a reply to. 00161 // 00162 00163 LpcpAcquireLpcpLock(); 00164 00165 if ( ( PortObject->ConnectedPort == NULL ) || 00166 ( PortObject->ConnectedPort->Flags & PORT_DELETED )) { 00167 00168 LpcpReleaseLpcpLock(); 00169 00170 ObDereferenceObject( PortObject ); 00171 ObDereferenceObject( ClientThread ); 00172 00173 return( STATUS_PORT_DISCONNECTED ); 00174 } 00175 00176 ConnectedPort = PortObject->ConnectedPort; 00177 ObReferenceObject( ConnectedPort ); 00178 00179 // 00180 // See if the thread is waiting for a reply to the message 00181 // specified on this call, if the user gave us a bad 00182 // message id. If not then a bogus message 00183 // has been specified, so return failure. 00184 // 00185 00186 if ((ClientThread->LpcReplyMessageId != CapturedMessageId) || 00187 (CapturedMessageId == 0)) { 00188 00189 LpcpReleaseLpcpLock(); 00190 00191 ObDereferenceObject( PortObject ); 00192 ObDereferenceObject( ClientThread ); 00193 ObDereferenceObject( ConnectedPort ); 00194 00195 return (STATUS_REPLY_MESSAGE_MISMATCH); 00196 } 00197 00198 // 00199 // Search in the LpcReplyChain if the ClientThread exists 00200 // Perform this search only if the client thread is queued to the port object 00201 // 00202 00203 if ( !IsListEmpty( &ClientThread->LpcReplyChain ) ) { 00204 00205 ThreadWaitingForReply = NULL; 00206 Head = &PortObject->LpcReplyChainHead; 00207 Next = Head->Flink; 00208 00209 while ((Next != NULL) && (Next != Head)) { 00210 00211 ThreadWaitingForReply = CONTAINING_RECORD( Next, ETHREAD, LpcReplyChain ); 00212 00213 // 00214 // If found the Client thread, quit from the loop 00215 // 00216 00217 if ( ThreadWaitingForReply == ClientThread) { 00218 00219 break; 00220 } 00221 00222 Next = Next->Flink; 00223 } 00224 00225 // 00226 // If not found, return an error 00227 // 00228 00229 if (ThreadWaitingForReply != ClientThread) { 00230 00231 LpcpReleaseLpcpLock(); 00232 00233 ObDereferenceObject( PortObject ); 00234 ObDereferenceObject( ClientThread ); 00235 ObDereferenceObject( ConnectedPort ); 00236 00237 return (STATUS_REPLY_MESSAGE_MISMATCH); 00238 } 00239 } 00240 00241 00242 LpcpReleaseLpcpLock(); 00243 00244 // 00245 // If the client requested dynamic security tracking, then the client 00246 // security needs to be referenced. Otherwise, (static case) 00247 // it is already in the client's port. 00248 // 00249 00250 if (ConnectedPort->Flags & PORT_DYNAMIC_SECURITY) { 00251 00252 // 00253 // Impersonate the client with information from the queued message 00254 // 00255 00256 Status = LpcpGetDynamicClientSecurity( ClientThread, 00257 PortObject->ConnectedPort, 00258 &DynamicSecurity ); 00259 00260 if (!NT_SUCCESS( Status )) { 00261 00262 ObDereferenceObject( PortObject ); 00263 ObDereferenceObject( ClientThread ); 00264 ObDereferenceObject( ConnectedPort ); 00265 00266 return( Status ); 00267 } 00268 00269 Status = SeImpersonateClientEx( &DynamicSecurity, NULL ); 00270 00271 LpcpFreeDynamicClientSecurity( &DynamicSecurity ); 00272 00273 } else { 00274 00275 // 00276 // Impersonate the client with information from the client's port 00277 // 00278 00279 Status = SeImpersonateClientEx( &ConnectedPort->StaticSecurity, NULL ); 00280 00281 } 00282 00283 ObDereferenceObject( PortObject ); 00284 ObDereferenceObject( ClientThread ); 00285 ObDereferenceObject( ConnectedPort ); 00286 00287 // 00288 // And return to our caller 00289 // 00290 00291 return Status; 00292 } 00293 00294 00295 VOID 00296 LpcpFreePortClientSecurity ( 00297 IN PLPCP_PORT_OBJECT Port 00298 ) 00299 00300 /*++ 00301 00302 Routine Description: 00303 00304 This routine cleans up the captured security context for a client port. 00305 The cleanup is typically done when we are deleting a port 00306 00307 Arguments: 00308 00309 Port - Supplies the client port being deleted 00310 00311 Return Value: 00312 00313 None. 00314 00315 --*/ 00316 00317 { 00318 // 00319 // We only do this action if supplied with a client communication port 00320 // 00321 00322 if ((Port->Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) { 00323 00324 // 00325 // We only do this action if the port has static security tracking, 00326 // and we have a captured client token. The action is to simply 00327 // delete the client token. 00328 // 00329 00330 if (!(Port->Flags & PORT_DYNAMIC_SECURITY)) { 00331 00332 if ( Port->StaticSecurity.ClientToken ) { 00333 00334 SeDeleteClientSecurity( &(Port)->StaticSecurity ); 00335 } 00336 } 00337 } 00338 00339 // 00340 // And return to our caller 00341 // 00342 00343 return; 00344 }

Generated on Sat May 15 19:40:39 2004 for test by doxygen 1.3.7