1 /* 2 * PROJECT: ReactOS Drivers 3 * COPYRIGHT: See COPYING in the top level directory 4 * PURPOSE: Kernel Security Support Provider Interface Driver 5 * 6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include "ksecdd.h" 12 #include <ksecioctl.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 18 /* FUNCTIONS ******************************************************************/ 19 20 static 21 NTSTATUS 22 KsecQueryFileInformation( 23 PVOID InfoBuffer, 24 FILE_INFORMATION_CLASS FileInformationClass, 25 PSIZE_T BufferLength) 26 { 27 PFILE_STANDARD_INFORMATION StandardInformation; 28 29 /* Only FileStandardInformation is supported */ 30 if (FileInformationClass != FileStandardInformation) 31 { 32 return STATUS_INVALID_INFO_CLASS; 33 } 34 35 /* Validate buffer size */ 36 if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) 37 { 38 *BufferLength = sizeof(FILE_STANDARD_INFORMATION); 39 return STATUS_INFO_LENGTH_MISMATCH; 40 } 41 42 /* Fill the structure */ 43 StandardInformation = (PFILE_STANDARD_INFORMATION)InfoBuffer; 44 StandardInformation->AllocationSize.QuadPart = 0; 45 StandardInformation->EndOfFile.QuadPart = 0; 46 StandardInformation->NumberOfLinks = 1; 47 StandardInformation->DeletePending = FALSE; 48 StandardInformation->Directory = FALSE; 49 *BufferLength = sizeof(FILE_STANDARD_INFORMATION); 50 51 return STATUS_SUCCESS; 52 } 53 54 static 55 NTSTATUS 56 KsecQueryVolumeInformation( 57 PVOID InfoBuffer, 58 FS_INFORMATION_CLASS FsInformationClass, 59 PSIZE_T BufferLength) 60 { 61 PFILE_FS_DEVICE_INFORMATION DeviceInformation; 62 63 /* Only FileFsDeviceInformation is supported */ 64 if (FsInformationClass != FileFsDeviceInformation) 65 { 66 return STATUS_INVALID_INFO_CLASS; 67 } 68 69 /* Validate buffer size */ 70 if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) 71 { 72 *BufferLength = sizeof(FILE_FS_DEVICE_INFORMATION); 73 return STATUS_INFO_LENGTH_MISMATCH; 74 } 75 76 /* Fill the structure */ 77 DeviceInformation = (PFILE_FS_DEVICE_INFORMATION)InfoBuffer; 78 DeviceInformation->DeviceType = FILE_DEVICE_NULL; 79 DeviceInformation->Characteristics = 0; 80 *BufferLength = sizeof(FILE_FS_DEVICE_INFORMATION); 81 82 return STATUS_SUCCESS; 83 } 84 85 static 86 NTSTATUS 87 KsecDeviceControl( 88 ULONG IoControlCode, 89 PVOID Buffer, 90 SIZE_T InputLength, 91 PSIZE_T OutputLength) 92 { 93 NTSTATUS Status; 94 95 if ((IoControlCode == IOCTL_KSEC_RANDOM_FILL_BUFFER) || 96 (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_PROCESS) || 97 (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_PROCESS) || 98 (IoControlCode == IOCTL_KSEC_ENCRYPT_CROSS_PROCESS) || 99 (IoControlCode == IOCTL_KSEC_DECRYPT_CROSS_PROCESS) || 100 (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_LOGON) || 101 (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_LOGON)) 102 { 103 /* Make sure we have a valid output buffer */ 104 if ((Buffer == NULL) || (OutputLength == NULL)) 105 { 106 return STATUS_INVALID_PARAMETER; 107 } 108 109 /* Check if the input is smaller than the output */ 110 if (InputLength < *OutputLength) 111 { 112 /* We might have uninitialized memory, zero it out */ 113 RtlSecureZeroMemory((PUCHAR)Buffer + InputLength, 114 *OutputLength - InputLength); 115 } 116 } 117 118 /* Check ioctl code */ 119 switch (IoControlCode) 120 { 121 case IOCTL_KSEC_REGISTER_LSA_PROCESS: 122 123 Status = STATUS_SUCCESS; 124 break; 125 126 case IOCTL_KSEC_RANDOM_FILL_BUFFER: 127 128 Status = KsecGenRandom(Buffer, *OutputLength); 129 break; 130 131 case IOCTL_KSEC_ENCRYPT_SAME_PROCESS: 132 133 Status = KsecEncryptMemory(Buffer, 134 *OutputLength, 135 RTL_ENCRYPT_OPTION_SAME_PROCESS); 136 break; 137 138 case IOCTL_KSEC_DECRYPT_SAME_PROCESS: 139 140 Status = KsecDecryptMemory(Buffer, 141 *OutputLength, 142 RTL_ENCRYPT_OPTION_SAME_PROCESS); 143 break; 144 145 case IOCTL_KSEC_ENCRYPT_CROSS_PROCESS: 146 147 Status = KsecEncryptMemory(Buffer, 148 *OutputLength, 149 RTL_ENCRYPT_OPTION_CROSS_PROCESS); 150 break; 151 152 case IOCTL_KSEC_DECRYPT_CROSS_PROCESS: 153 154 Status = KsecDecryptMemory(Buffer, 155 *OutputLength, 156 RTL_ENCRYPT_OPTION_CROSS_PROCESS); 157 break; 158 159 case IOCTL_KSEC_ENCRYPT_SAME_LOGON: 160 161 Status = KsecEncryptMemory(Buffer, 162 *OutputLength, 163 RTL_ENCRYPT_OPTION_SAME_LOGON); 164 break; 165 166 case IOCTL_KSEC_DECRYPT_SAME_LOGON: 167 168 Status = KsecDecryptMemory(Buffer, 169 *OutputLength, 170 RTL_ENCRYPT_OPTION_SAME_LOGON); 171 break; 172 173 default: 174 DPRINT1("Unhandled control code 0x%lx\n", IoControlCode); 175 __debugbreak(); 176 return STATUS_INVALID_PARAMETER; 177 } 178 179 return Status; 180 } 181 182 NTSTATUS 183 NTAPI 184 KsecDdDispatch( 185 PDEVICE_OBJECT DeviceObject, 186 PIRP Irp) 187 { 188 PIO_STACK_LOCATION IoStackLocation; 189 ULONG_PTR Information; 190 NTSTATUS Status; 191 PVOID Buffer; 192 SIZE_T InputLength, OutputLength; 193 FILE_INFORMATION_CLASS FileInfoClass; 194 FS_INFORMATION_CLASS FsInfoClass; 195 ULONG IoControlCode; 196 197 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 198 199 switch (IoStackLocation->MajorFunction) 200 { 201 case IRP_MJ_CREATE: 202 case IRP_MJ_CLOSE: 203 204 /* Just return success */ 205 Status = STATUS_SUCCESS; 206 Information = 0; 207 break; 208 209 case IRP_MJ_READ: 210 211 /* There is nothing to read */ 212 Status = STATUS_END_OF_FILE; 213 Information = 0; 214 break; 215 216 case IRP_MJ_WRITE: 217 218 /* Pretend to have written everything */ 219 Status = STATUS_SUCCESS; 220 Information = IoStackLocation->Parameters.Write.Length; 221 break; 222 223 case IRP_MJ_QUERY_INFORMATION: 224 225 /* Extract the parameters */ 226 Buffer = Irp->AssociatedIrp.SystemBuffer; 227 OutputLength = IoStackLocation->Parameters.QueryFile.Length; 228 FileInfoClass = IoStackLocation->Parameters.QueryFile.FileInformationClass; 229 230 /* Call the internal function */ 231 Status = KsecQueryFileInformation(Buffer, 232 FileInfoClass, 233 &OutputLength); 234 Information = OutputLength; 235 break; 236 237 case IRP_MJ_QUERY_VOLUME_INFORMATION: 238 239 /* Extract the parameters */ 240 Buffer = Irp->AssociatedIrp.SystemBuffer; 241 OutputLength = IoStackLocation->Parameters.QueryVolume.Length; 242 FsInfoClass = IoStackLocation->Parameters.QueryVolume.FsInformationClass; 243 244 /* Call the internal function */ 245 Status = KsecQueryVolumeInformation(Buffer, 246 FsInfoClass, 247 &OutputLength); 248 Information = OutputLength; 249 break; 250 251 case IRP_MJ_DEVICE_CONTROL: 252 253 /* Extract the parameters */ 254 InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength; 255 OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength; 256 IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode; 257 258 /* Check for METHOD_OUT_DIRECT method */ 259 if ((METHOD_FROM_CTL_CODE(IoControlCode) == METHOD_OUT_DIRECT) && 260 (OutputLength != 0)) 261 { 262 /* Use the provided MDL */ 263 OutputLength = Irp->MdlAddress->ByteCount; 264 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, 265 NormalPagePriority); 266 if (Buffer == NULL) 267 { 268 Status = STATUS_INSUFFICIENT_RESOURCES; 269 Information = 0; 270 break; 271 } 272 } 273 else 274 { 275 /* Otherwise this is METHOD_BUFFERED, use the SystemBuffer */ 276 Buffer = Irp->AssociatedIrp.SystemBuffer; 277 } 278 279 /* Call the internal function */ 280 Status = KsecDeviceControl(IoControlCode, 281 Buffer, 282 InputLength, 283 &OutputLength); 284 Information = OutputLength; 285 break; 286 287 default: 288 DPRINT1("Unhandled major function %lu!\n", 289 IoStackLocation->MajorFunction); 290 ASSERT(FALSE); 291 return STATUS_INVALID_DEVICE_REQUEST; 292 } 293 294 /* Return the information */ 295 Irp->IoStatus.Status = Status; 296 Irp->IoStatus.Information = Information; 297 298 /* Complete the request */ 299 IoCompleteRequest(Irp, IO_NO_INCREMENT); 300 301 return Status; 302 } 303