1 /* 2 * Copyright © [2008-2009] Novell, Inc. All Rights Reserved. 3 * 4 * USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE DEVELOPER LICENSE AGREEMENT 5 * OR OTHER AGREEMENT THROUGH WHICH NOVELL, INC. MAKES THE WORK AVAILABLE. THIS WORK 6 * MAY NOT BE ADAPTED WITHOUT NOVELL'S PRIOR WRITTEN CONSENT. 7 * 8 * NOVELL PROVIDES THE WORK "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 * INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR 10 * A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. NOVELL, THE AUTHORS OF THE WORK, AND THE 11 * OWNERS OF COPYRIGHT IN THE WORK ARE NOT LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 12 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, 13 * OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK. 14 */ 15 16 /** 17 * @fileoverview 18 * This file defines the Event class, which represents the output event that will be 19 * sent to Sentinel. 20 * @name Event Class 21 */ 22 23 /** 24 * Constructs a new instance of an Event object, which can be sent to Sentinel. 25 * The constructor can take an object or JSON string as input to set pre-defined 26 * fields, e.g. constants for initialization of the new Event object. 27 * @class 28 * Represents a Sentinel event that can be sent up to the Collector Manager. 29 * In general, Event objects are not manipulated directly as the field values 30 * need to be protected, but are manipulated via methods. 31 * @param {Event} proto The prototype or template event that should be cloned to create this new Event 32 */ 33 function Event(proto) { 34 for (var src in proto) { 35 if ( proto.hasOwnProperty(src) ) { 36 this[src] = proto[src]; 37 } 38 } 39 }; 40 41 /** 42 * Sets the ObserverEventTime and ObserverEventTimeString to the time according to the event source. 43 * The Sentinel event schema includes two fields: 44 * <dl> 45 * <dt>ObserverEventTimeString</dt><dd>A string representation of the time, according to the event source, that the event occurred.</dd> 46 * <dt>ObserverEventTime</dt><dd>A timestamp representation of the time, according to the event source, that the event occurred; if the event source clock is trusted, this will be copied to EventTime.</dd> 47 * </dl> 48 * Both fields will be set by this method. 49 * <p>Note that you must pass a Date object to this method; you must therefore first convert whatever 50 * textual representation of the date and time is embedded in the input record into a Date object. 51 * We have included the <a href="http://www.datejs.com/">date.js library</a> to make this easier. You 52 * should be able to pass it almost any datetime representation and have it correctly create a Date, 53 * but note that in some cases you may need to add missing year and/or timezone information. 54 * @example 55 * Record.prototype.parse = function(e) { 56 * this.devtime = Date.parse(this.s_RXBufferString.substr(0,30)); 57 * e.setObserverEventTime(this.devtime); 58 * 59 * @param {Date} time The date/time according to the event source. This MUST be a Date object. 60 * @return {Boolean} A Boolean to indicate successful completion 61 */ 62 Event.prototype.setObserverEventTime = function(time){ 63 if ( !(time instanceof Date) ) { return false; } 64 this.ObserverEventTime = time; 65 return true; 66 }; 67 68 /** 69 * Sets the BeginTime field to the time the event(s) began according to the event source. 70 * <p>Note that you must pass a Date object to this method; you must therefore first convert whatever 71 * textual representation of the date and time is embedded in the input record into a Date object. 72 * We have included the <a href="http://www.datejs.com/">date.js library</a> to make this easier. You 73 * should be able to pass it almost any datetime representation and have it correctly create a Date, 74 * but note that in some cases you may need to add missing year and/or timezone information. 75 * @example 76 * Record.prototype.parse = function(e) { 77 * this.begintime = Date.parse(this.s_RXBufferString.substr(0,30)); 78 * e.setBeginTime(this.begintime); 79 * 80 * @param {Date} time The date/time the event(s) began according to the event source. This MUST be a Date object. 81 * @return {Boolean} A Boolean to indicate successful completion 82 */ 83 Event.prototype.setBeginTime = function(time){ 84 if ( !(time instanceof Date) ) { return false; } 85 this.BeginTime = time; 86 return true; 87 }; 88 89 /** 90 * Sets the EndTime field to the time the event(s) ended according to the event source. 91 * <p>Note that you must pass a Date object to this method; you must therefore first convert whatever 92 * textual representation of the date and time is embedded in the input record into a Date object. 93 * We have included the <a href="http://www.datejs.com/">date.js library</a> to make this easier. You 94 * should be able to pass it almost any datetime representation and have it correctly create a Date, 95 * but note that in some cases you may need to add missing year and/or timezone information. 96 * @example 97 * Record.prototype.parse = function(e) { 98 * this.endtime = Date.parse(this.s_RXBufferString.substr(0,30)); 99 * e.setEndTime(this.endtime); 100 * 101 * @param {Date} time The date/time the event(s) ended according to the event source. This MUST be a Date object. 102 * @return {Boolean} A Boolean to indicate successful completion 103 */ 104 Event.prototype.setEndTime = function(time){ 105 if ( !(time instanceof Date) ) { return false; } 106 this.EndTime = time; 107 return true; 108 }; 109 110 /** 111 * Adds the arguments to the Sentinel ExtendedInformation field. 112 * Sentinel's ExtendedInformation field has a pre-defined internal format as name-value pair. 113 * To enforce this format, use this method to add data to this field. 114 * <p>Example: 115 * <pre> 116 * curEvt.add2EI( "CustomData", rec.s_RXBufferString.substr(20,30); 117 * </pre> 118 * @param {String} name The attribute name that will be set 119 * @param {String} val The value for that attribute 120 * @return {Boolean} A Boolean to indicate successful completion 121 */ 122 Event.prototype.add2EI = function(name, val){ 123 if (typeof name == "undefined" || typeof val == "undefined" || name === "" || val === "") { 124 return false; 125 } 126 if (typeof this.EIObj == "undefined") { 127 this.EIObj = {}; 128 } 129 this.EIObj[name] = val; 130 return true; 131 }; 132 133 /** 134 * Sets the taxonomy key to be used when constructing the output Event. 135 * The taxonomy key is used to determine the taxonomy classification for the event. It 136 * should include enough information to determine the type of action taken as well as the 137 * outcome of the event (status or result). The key needs to match one of the entries in 138 * the taxonomy {@link KeyMap}, which is loaded from the taxonomy.map file. 139 * <p>The taxonomy key is used to set the following Event fields: 140 * <ul> 141 * <li>Event.TaxonomyLevel1 142 * <li>Event.TaxonomyLevel2 143 * <li>Event.TaxonomyLevel3 144 * <li>Event.TaxonomyLevel4 145 * <li>Event.XDASEventName 146 * <li>Event.XDASEventOutcome 147 * <li>Event.XDASRegistry 148 * <li>Event.XDASProvider 149 * <li>Event.XDASClass 150 * <li>Event.XDASIdentifier 151 * <li>Event.XDASOutcome 152 * <li>Event.XDASDetail 153 * </ul> 154 * @param {String} key The string to use as the taxonomy key 155 * @return {Boolean} Result 156 */ 157 Event.prototype.setTaxKey = function(key){ 158 // Use key to look up taxonomy 159 if (typeof key == "undefined") { return false; } 160 var taxonomy = instance.MAPS.tax.lookup(key); 161 if (typeof taxonomy == "undefined") { return false; } 162 this.XDASTaxonomyName = taxonomy[0]; 163 this.XDASOutcomeName = taxonomy[1]; 164 var taxcode = instance.MAPS.taxcode.lookup(this.XDASTaxonomyName); 165 var taxout = instance.MAPS.taxout.lookup(this.XDASOutcomeName); 166 this.XDASRegistry = taxcode[0]; 167 this.XDASProvider = taxcode[1]; 168 this.XDASClass = taxcode[2]; 169 this.XDASIdentifier = taxcode[3]; 170 if (instance.CONFIG.params.addLegacyTaxonomy) { 171 this.TaxonomyLevel1 = taxcode[4]; 172 this.TaxonomyLevel2 = taxcode[5]; 173 this.TaxonomyLevel3 = taxcode[6]; 174 } 175 this.XDASOutcome = taxout[0]; 176 this.XDASDetail = taxout[1]; 177 if (instance.CONFIG.params.addLegacyTaxonomy) { 178 switch (this.XDASOutcome) { 179 case "1": 180 this.TaxonomyLevel3 = this.TaxonomyLevel3 + " FAILED"; 181 break; 182 case "2": 183 this.TaxonomyLevel3 = this.TaxonomyLevel3 + " DENIED"; 184 break; 185 case "0": 186 case "3": 187 default: 188 break; 189 } 190 } 191 return true; 192 }; 193 194 /** 195 * Sends an event to the Collector Manager. 196 * This method consumes the input record object to set fields in the output event, 197 * as well as performing some additional processing. 198 * @param {DataMap} datamap The map to use (optional) when converting the 'rec' object into the Event. Will default to Rec2Evt. 199 * @return {Boolean} Result 200 */ 201 Event.prototype.send = function(datamap) { 202 203 if (typeof datamap == "undefined") { 204 datamap = instance.MAPS.Rec2Evt; 205 } 206 207 // Convert record to output event (if this is not an internal event) 208 if (typeof rec != "undefined") { 209 rec.convert(this, datamap); 210 } 211 else { // probably a debug event with no input record; need a blank one 212 rec = new Record(); 213 var hashMap = new HashMap(); 214 rec.connectorData = new ConnectorData(hashMap); 215 } 216 217 // Create a JSON EI string 218 if (typeof this.EIObj != "undefined") { 219 this.ExtendedInformation = JSON.stringify(this.EIObj); 220 delete this.EIObj; 221 } 222 223 // Produce debug output 224 if (instance.CONFIG.params.ExecutionMode == "debug") { 225 instance.CONFIG.debugFile.writeLine(JSON.stringify(this) + "\n"); 226 } 227 228 // Mark replay events 229 if (rec.CONNECTION_REPLAY == true) { 230 this.ObserverType="T"; 231 } 232 233 // resolve hostnames if asked 234 if (instance.CONFIG.params.Resolve_IP_and_Hostname) { 235 var assets = {"Source":null,"Target":null,"Observer":null,"Reporter":null}; 236 237 var unknownIPs = []; 238 var unknownHosts = []; 239 var fqdn; 240 241 for (var asset in assets) { 242 if (typeof this[asset + "HostName"] == 'undefined') { // Need the hostname 243 if (typeof this[asset + "IP"] != 'undefined') { 244 if (typeof instance.MAPS.ip2n[this[asset + "IP"]] != 'undefined') { 245 fqdn = instance.MAPS.ip2n[this[asset + "IP"]][0]; 246 if (fqdn.search(/\./) != -1) { 247 this[asset + "HostName"] = fqdn.substr(0, fqdn.indexOf(".")); 248 this[asset + "HostDomain"] = fqdn.substr(fqdn.indexOf(".") + 1); 249 } else { 250 this[asset + "HostName"] = fqdn; 251 } 252 } else { 253 unknownIPs.push(this[asset + "IP"]); 254 } 255 } 256 } else { // Need the IP 257 if (typeof this[asset + "IP"] == 'undefined') { 258 if (typeof this[asset + "HostName"] != 'undefined' && typeof this[asset + "HostDomain"] != 'undefined') { 259 fqdn = this[asset + "HostName"] + "." + this[asset + "HostDomain"]; 260 } else if (typeof this[asset + "HostName"] != 'undefined' && typeof this[asset + "HostDomain"] == 'undefined') { 261 fqdn = this[asset + "HostName"]; 262 } 263 if (typeof fqdn != 'undefined') { 264 if (typeof instance.MAPS.n2ip[fqdn] != 'undefined') { 265 this[asset + "IP"] = instance.MAPS.n2ip[fqdn][0]; 266 } else { 267 unknownHosts.push(fqdn); 268 } 269 } 270 } 271 } 272 } 273 274 if (unknownIPs.length > 0) { 275 var needIPsFile = new File(instance.CONFIG.commonDir + instance.UUID + ".needIPs.tmp", "w"); 276 for (var i = unknownIPs.length - 1; i > -1; i--) { 277 needIPsFile.writeLine(unknownIPs[i]); 278 } 279 needIPsFile.close(); 280 } 281 if (unknownHosts.length > 0) { 282 var needHostsFile = new File(instance.CONFIG.commonDir + instance.UUID + ".needHosts.tmp", "w"); 283 for (i = unknownHosts.length - 1; i > -1; i--) { 284 needHostsFile.writeLine(unknownHosts[i]); 285 } 286 needHostsFile.close(); 287 } 288 } // end name resolution 289 290 if (instance.CONFIG.params.Resolve_IP_To_User) { 291 // Store a user if they log in 292 if (this.XDASClass == "2" && this.XDASIdentifier == "0" && this.XDASOutcome == "0" && 293 (typeof this.TargetUserName != "undefined" || this.TargetUserName != "") && 294 (typeof this.TargetUserID != "undefined" || this.TargetUserID != "") && 295 typeof this.TargetIP != "undefined" && this.TargetIP != "") { 296 var ip2uFile = new File(instance.CONFIG.commonDir + instance.UUID + ".ip2u.tmp", "w"); 297 ip2uFile.writeLine(this.TargetIP + "," + this.TargetUserName + 298 "," + this.TargetUserDomain + "," + this.TargetUserID); 299 ip2uFile.close(); 300 } 301 // If InitiatorUserName is unset, try to find it 302 if (typeof this.InitiatorUserName == "undefined" && typeof this.InitiatorUserID == "undefined" && 303 typeof this.SourceIP != undefined && this.SourceIP != "") { 304 var userinfo = instance.MAPS.ip2u.lookup[this.SourceIP]; 305 if (typeof userinfo[0] != "undefined" && userinfo[0] != "") { 306 this.InitiatorUserName = userinfo[0]; 307 } 308 if (typeof userinfo[1] != "undefined" && userinfo[1] != "") { 309 this.InitiatorUserDomain = userinfo[1]; 310 } 311 if (typeof userinfo[2] != "undefined" && userinfo[2] != "") { 312 this.InitiatorUserID = userinfo[2]; 313 } 314 } 315 } // end user resolution 316 317 // Look up privilege level of users if provided 318 if (instance.CONFIG.params.lookupPriv && typeof this.InitiatorUserName != "undefined" && this.InitiatorUserName != "") { 319 var pl; 320 pl = instance.MAPS.privLevel.lookup(this.InitiatorUserName); 321 if (typeof pl != "undefined") { 322 this.InitiatorUserPrivilegeLevel = pl[0]; 323 } else { 324 this.InitiatorUserPrivilegeLevel = 0; 325 } 326 } 327 328 // Look up the sensitivity of the target data object 329 if (instance.CONFIG.params.lookupSens) { 330 var pl; 331 if (typeof this.TargetDataNamespace != "undefined" && this.TargetDataNamespace != "") { 332 pl = instance.MAPS.sensitivity.lookup(this.TargetDataNamespace + ":" + this.TargetDataContainer + "/" + this.TargetDataName); 333 if (typeof pl != "undefined") { 334 this.TargetDataSensitivity = pl[0]; 335 } 336 } 337 if (typeof pl == "undefined" && typeof this.TargetDataContainer != "undefined" && this.TargetDataName != "") { 338 pl = instance.MAPS.sensitivity.lookup(this.TargetDataContainer + "/" + this.TargetDataName); 339 if (typeof pl != "undefined") { 340 this.TargetDataSensitivity = pl[0]; 341 } 342 } 343 if (typeof pl == "undefined") { 344 pl = instance.MAPS.sensitivity.lookup(this.TargetDataContainer + "/"); 345 if (typeof pl != "undefined") { 346 this.TargetDataSensitivity = pl[0]; 347 } else { 348 this.TargetDataSensitivity = 0; 349 } 350 } 351 } 352 353 // Set the ObserverTZ based on the record 354 this.ObserverTZ = rec.s_TimeZone; 355 356 // Make sure that we don't try to set new schema fields on old platforms 357 if (instance.CONFIG.params.schemaVersion < 700) { 358 for (var field in this) { 359 switch (field) { 360 361 case "InitiatorUserPrivilegeLevel": 362 case "SourceMAC": 363 case "SourceTranslatedIP": 364 case "SourceTranslatedMAC": 365 case "SourceTranslatedPort": 366 case "VendorOutcomeCode": 367 case "PolicyID": 368 case "SessionID": 369 case "ObserverTZ": 370 case "TargetMAC": 371 case "TargetTranslatedIP": 372 case "TargetTranslatedPort": 373 case "TargetTranslatedMAC": 374 case "TargetDataNamespace": 375 case "TargetDataSensitivity": 376 case "TargetNewResourceName": 377 case "TargetNewResourceType": 378 case "TargetNewResourceContainer": 379 case "TargetNewResourceNamespace": 380 case "TargetAttributeName": 381 case "ObserverMAC": 382 case "ObserverServiceName": 383 case "ReporterMAC": 384 this.add2EI(field, this[field]); 385 delete this[field]; 386 break; 387 default: 388 break; 389 } 390 } 391 } 392 393 // Construct the Java event from the JS event 394 var JEvent = new EventData(); 395 for (var field in this) { 396 if (this.hasOwnProperty(field)) { 397 var value = this[field]; 398 if (value != "" && instance.MAPS.Evt2EvtData[field] && typeof value != "undefined" && value != "undefined" 399 && field != "ObserverEventTime" && field != "BeginTime" && field != "EndTime" && field != "length") { 400 JEvent.setString(instance.MAPS.Evt2EvtData[field], String(value)); 401 } 402 } 403 } 404 405 // Set ObserverEventTime and ObserverEventTimeString 406 if (this.ObserverEventTime instanceof Date) { 407 this.ObserverEventTime.adjustTimezone(); 408 JEvent.setDeviceEventTime(String(this.ObserverEventTime.getTime())); 409 JEvent.setString( "et", this.ObserverEventTime.toString()); 410 } 411 412 // Set BeginTime and EndTime 413 if (this.BeginTime instanceof Date) { 414 this.BeginTime.adjustTimezone(); 415 JEvent.setString("bgnt", String(this.BeginTime.getTime())); 416 } 417 if (this.EndTime instanceof Date) { 418 this.EndTime.adjustTimezone(); 419 JEvent.setString("endt", String(this.EndTime.getTime())); 420 } 421 // Send event 422 instance.CONFIG.scriptContext.fireEvent(JEvent, rec.connectorData); 423 return true; 424 }; 425