using System; using System.Web; using System.Text; using System.Web.Services; using System.Web.Services.Protocols; using System.Xml; using System.IO; using System.Net; using System.Net.Security; [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.Web.Services.WebServiceAttribute(Namespace = "http://www.wisconsin.gov/wijis/gateway/RecordRetrievalService/")] // implementing the RecordRetrievalService Interface IRecordRetrievalserviceSOAP public class RecordRetrievalService : System.Web.Services.WebService, IRecordRetrievalServiceSOAP { private WijisMessageTrackingInfoType messageTrackingInfoField; private StringBuilder sb; private ClientCertStatus clientCertStatus; private enum ResponseType {INCIDENTREPORT , NORECORD, CONTACTINFO, ERROR}; private enum ClientCertStatus { NOERRORS, TIMEERROR, NOTTRUSTED, CNNOTMATCH, NOTPRESENT }; private static ResponseType responseType = ResponseType.INCIDENTREPORT; public WijisMessageTrackingInfoType messageTrackingInfo { get { return this.messageTrackingInfoField; } set { this.messageTrackingInfoField = value; } } private ClientCertStatus ValidateClientCert() { HttpClientCertificate cert = Context.Request.ClientCertificate; #region VerboseDebugging if (cert != null) sb = new StringBuilder(); DateTime dtNow = DateTime.Now; sb.Append("Client Certificate Received:\t"); sb.Append(dtNow.ToString("yyyy-MM-dd hh:mm:ss tt")); sb.Append(Environment.NewLine); sb.Append("IsPresent:\t"); sb.Append(cert.IsPresent); sb.Append(Environment.NewLine); sb.Append("Encoding:\t"); sb.Append(cert.CertEncoding); sb.Append(Environment.NewLine); sb.Append("Issuer:\t"); sb.Append(cert.Issuer); sb.Append(Environment.NewLine); //The client certificate is not valid if the Certificate //Authority (CA) is not in the list of recognized CAs on the server. sb.Append("IsValid:\t"); sb.Append(cert.IsValid); sb.Append(Environment.NewLine); sb.Append("SerialNumber:\t"); sb.Append(cert.SerialNumber); sb.Append(Environment.NewLine); sb.Append("ServerIssuer:\t"); sb.Append(cert.ServerIssuer); sb.Append(Environment.NewLine); sb.Append("ServerSubject:\t"); sb.Append(cert.ServerSubject); sb.Append(Environment.NewLine); sb.Append("Subject:\t"); sb.Append(cert.Subject); sb.Append(Environment.NewLine); sb.Append("ValidFrom:\t"); sb.Append(cert.ValidFrom.ToString("yyyy-MM-dd hh:mm:ss tt")); sb.Append(Environment.NewLine); sb.Append("ValidUntil:\t"); sb.Append(cert.ValidUntil.ToString("yyyy-MM-dd hh:mm:ss tt")); sb.Append(Environment.NewLine); #endregion #region Check to see that cert is present if (!cert.IsPresent) { return ClientCertStatus.NOTPRESENT; } #endregion #region Check to see that cert is valid, trusted ca if (!cert.IsValid) { return ClientCertStatus.NOTTRUSTED; } #endregion #region Check to see that cert is from a machine that we actually trust if (cert.Subject.Contains("CN=labdc.doa.wistate.us") || cert.Subject.Contains("CN=wijis.wisconsin.gov") || cert.Subject.Contains("CN=wijisgwtest.wisconsin.gov") ) { } else { ApplicationEventLog.WriteError(cert.Subject + Environment.NewLine + "Attempted to access the service and is not allowed to do so." + Environment.NewLine); return ClientCertStatus.CNNOTMATCH; //TODO: Eventually you probably want to throw an exception here to prevent //anyone with a certificate that you are not expecting to not get access to the service //throw new Exception("Invalid Certificate"); } #endregion #region Check to see that cert is within the valid time window if (DateTime.Now > cert.ValidUntil || DateTime.Now < cert.ValidFrom) { return ClientCertStatus.TIMEERROR; } #endregion return ClientCertStatus.NOERRORS; } public RecordRetrievalService() { //Uncomment the following line if using designed components //InitializeComponent(); } private void CreateResponseMessageTrackingInfo() { messageTrackingInfo.convSeq += 1; // get the value equivalent to java's System.currentTimeMillis() // and set it to serviceInvocationNum. TimeSpan span = DateTime.UtcNow - new DateTime(1970, 1, 1); long millis = (long)span.TotalMilliseconds; messageTrackingInfo.serviceInvocationNum = millis.ToString(); messageTrackingInfo.currentServiceDefURI = messageTrackingInfo.currentServiceDefURI.Replace("request", "response"); messageTrackingInfo.currentServiceLabel = "Record Retrieval Response to WIJIS"; string currentServiceProviderURI = messageTrackingInfo.currentServiceProviderURI; messageTrackingInfo.currentServiceProviderURI = messageTrackingInfo.currentSendingOperatorURI; messageTrackingInfo.currentSendingOperatorURI = currentServiceProviderURI; } public recordRetrievalResponse returnContactInfoResponse(RecordRetrievalInvocationType recordRetrieval) { recordRetrievalResponse recordRetrievalResponse = new recordRetrievalResponse(); RecordRetrievalConfirmationType confirmation = new RecordRetrievalConfirmationType(); confirmation.recordURI = recordRetrieval.recordURI; WijisServiceResponseInfoItemsType infoItems = new WijisServiceResponseInfoItemsType(); WijisServiceResponseInfoItemType item = new WijisServiceResponseInfoItemType(); item.timestamp = DateTime.Now; item.timestampSpecified = true; item.recordDesignator = "WIJIS"; ContactInfoContact recordSourceContactInfo = new ContactInfoContact(); recordSourceContactInfo.contactName = "Homer"; recordSourceContactInfo.email = new string[] { "homer.simpson@wisconsin.gov" }; recordSourceContactInfo.faxNum = new string[] { "233-3333" }; recordSourceContactInfo.phoneNum = new string[] { "233-3334" }; infoItems.info = new WijisServiceResponseInfoItemType[] { item }; confirmation.infoItems = new WijisServiceResponseInfoItemsType[] { infoItems }; confirmation.Item = new ContactInfoContact[] { recordSourceContactInfo }; confirmation.recordCount = "0"; recordRetrievalResponse.Item = confirmation; return recordRetrievalResponse; } public recordRetrievalResponse returnNoRecordResponse(RecordRetrievalInvocationType recordRetrieval) { recordRetrievalResponse recordRetrievalResponse = new recordRetrievalResponse(); RecordRetrievalConfirmationType confirmation = new RecordRetrievalConfirmationType(); confirmation.recordURI = recordRetrieval.recordURI; // Might or might not need the commented part. /* WijisServiceResponseInfoItemsType infoItems = new WijisServiceResponseInfoItemsType(); WijisServiceResponseInfoItemType item = new WijisServiceResponseInfoItemType(); item.timestamp = DateTime.Now; item.timestampSpecified = true; item.recordDesignator = "WIJIS"; infoItems.info = new WijisServiceResponseInfoItemType[] { item }; confirmation.infoItems = new WijisServiceResponseInfoItemsType[] { infoItems }; */ confirmation.Item = "No Record Found"; confirmation.recordCount = "0"; recordRetrievalResponse.Item = confirmation; return recordRetrievalResponse; } public recordRetrievalResponse returnErrorResponse(RecordRetrievalInvocationType recordRetrieval) { recordRetrievalResponse recordRetrievalResponse = new recordRetrievalResponse(); //create errorItems. WijisServiceResponseErrorItemType item = new WijisServiceResponseErrorItemType(); item.severity = WijisErrorSeverityType.fatal; item.timestamp = DateTime.UtcNow; if (!this.clientCertStatus.Equals(ClientCertStatus.NOERRORS)) { item.Value = String.Concat("Client Cert Error:" , clientCertStatus.ToString(), "" , sb.ToString()); } else { item.Value = "Something else other than the clientCert is very wrong!"; } WijisServiceResponseErrorItemsType errorItems = new WijisServiceResponseErrorItemsType(); errorItems.Items = new WijisServiceResponseErrorItemType[] { item }; // RecordRetrievalErrorType error = new RecordRetrievalErrorType(); error.recordURI = recordRetrieval.recordURI; error.errorItems = new WijisServiceResponseErrorItemsType[] { errorItems }; recordRetrievalResponse.Item = error; return recordRetrievalResponse; } [WebMethod] public recordRetrievalResponse retrieveRecords(RecordRetrievalInvocationType recordRetrieval) { CreateResponseMessageTrackingInfo(); recordRetrievalResponse recordRetrievalResponse = null; this.clientCertStatus = ValidateClientCert(); if (this.clientCertStatus.Equals(ClientCertStatus.NOERRORS)) { /* * make different responses in turn. */ switch (RecordRetrievalService.responseType) { case ResponseType.INCIDENTREPORT: IncidentReportMgr objIncidentReportMgr = new IncidentReportMgr(); recordRetrievalResponse = objIncidentReportMgr.returnIncidentReportResponse(recordRetrieval); RecordRetrievalService.responseType++; break; case ResponseType.NORECORD: recordRetrievalResponse = returnNoRecordResponse(recordRetrieval); RecordRetrievalService.responseType++; break; case ResponseType.CONTACTINFO: recordRetrievalResponse = returnContactInfoResponse(recordRetrieval); RecordRetrievalService.responseType++; break; default: recordRetrievalResponse = returnErrorResponse(recordRetrieval); RecordRetrievalService.responseType = ResponseType.INCIDENTREPORT; break; } } else { recordRetrievalResponse = returnErrorResponse(recordRetrieval); } return recordRetrievalResponse; } }