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 DeviceEventTime and DeviceEventTimeString to the time according to the event source. 43 * The Sentinel event schema includes two fields: 44 * <dl> 45 * <dt>DeviceEventTimeString</dt><dd>A string which represents the time according to the event source; 46 * this is always expressed in local time according to the Collector Manager, since that's where the time is processed.</dd> 47 * <dt>DeviceEventTime</dt><dd>A field of Date type which represents the time according to the event source</dd> 48 * </dl> 49 * Both fields will be set by this method. 50 * <p>Note that you must pass a Date object to this method; you must therefore first convert whatever 51 * textual representation of the date and time is embedded in the input record into a Date object. 52 * We have included the <a href="http://www.datejs.com/">date.js library</a> to make this easier. You 53 * should be able to pass it almost any datetime representation and have it correctly create a Date, 54 * but note that in some cases you may need to add missing year and/or timezone information. 55 * @example 56 * Record.prototype.parse = function(e) { 57 * this.devtime = Date.parse(this.s_RXBufferString.substr(0,30)); 58 * e.setDeviceEventTime(this.devtime); 59 * 60 * @param {Date} time The date/time according to the event source. This MUST be a Date object. 61 * @return {Boolean} A Boolean to indicate successful completion 62 */ 63 Event.prototype.setDeviceEventTime = function(time){ 64 65 if ( !(time instanceof Date) ) { return false; } 66 this.DeviceEventTime = time; 67 return true; 68 }; 69 70 /** 71 * Sets the BeginTime field to the time the event(s) began according to the event source. 72 * <p>Note that you must pass a Date object to this method; you must therefore first convert whatever 73 * textual representation of the date and time is embedded in the input record into a Date object. 74 * We have included the <a href="http://www.datejs.com/">date.js library</a> to make this easier. You 75 * should be able to pass it almost any datetime representation and have it correctly create a Date, 76 * but note that in some cases you may need to add missing year and/or timezone information. 77 * @example 78 * Record.prototype.parse = function(e) { 79 * this.begintime = Date.parse(this.s_RXBufferString.substr(0,30)); 80 * e.setBeginTime(this.begintime); 81 * 82 * @param {Date} time The date/time the event(s) began according to the event source. This MUST be a Date object. 83 * @return {Boolean} A Boolean to indicate successful completion 84 */ 85 Event.prototype.setBeginTime = function(time){ 86 87 if ( !(time instanceof Date) ) { return false; } 88 this.BeginTime = time; 89 return true; 90 }; 91 92 /** 93 * Sets the EndTime field to the time the event(s) ended according to the event source. 94 * <p>Note that you must pass a Date object to this method; you must therefore first convert whatever 95 * textual representation of the date and time is embedded in the input record into a Date object. 96 * We have included the <a href="http://www.datejs.com/">date.js library</a> to make this easier. You 97 * should be able to pass it almost any datetime representation and have it correctly create a Date, 98 * but note that in some cases you may need to add missing year and/or timezone information. 99 * @example 100 * Record.prototype.parse = function(e) { 101 * this.endtime = Date.parse(this.s_RXBufferString.substr(0,30)); 102 * e.setEndTime(this.endtime); 103 * 104 * @param {Date} time The date/time the event(s) ended according to the event source. This MUST be a Date object. 105 * @return {Boolean} A Boolean to indicate successful completion 106 */ 107 Event.prototype.setEndTime = function(time){ 108 109 if ( !(time instanceof Date) ) { return false; } 110 this.EndTime = time; 111 return true; 112 }; 113 114 /** 115 * Adds the arguments to the Sentinel ExtendedInformation field. 116 * Sentinel's ExtendedInformation field has a pre-defined internal format as name-value pair. 117 * To enforce this format, use this method to add data to this field. 118 * <p>Example: 119 * <pre> 120 * curEvt.add2EI( "CustomData", rec.s_RXBufferString.substr(20,30); 121 * </pre> 122 * @param {String} name The attribute name that will be set 123 * @param {String} val The value for that attribute 124 * @return {Boolean} A Boolean to indicate successful completion 125 */ 126 Event.prototype.add2EI = function(name, val){ 127 if (typeof name == "undefined" || typeof val == "undefined" || name === "" || val === "") { 128 return false; 129 } 130 this.ExtendedInformation = this.ExtendedInformation ? (this.ExtendedInformation + " " + name + "=" + val + ";") : (name + "=" + val + ";"); 131 return true; 132 }; 133 134 /** 135 * Sets the taxonomy key to be used when constructing the output Event. 136 * The taxonomy key is used to determine the taxonomy classification for the event. It 137 * should include enough information to determine the type of action taken as well as the 138 * outcome of the event (status or result). The key needs to match one of the entries in 139 * the taxonomy {@link KeyMap}, which is loaded from the taxonomy.map file. 140 * <p>The taxonomy key is used to set the following Event fields: 141 * <ul> 142 * <li>Event.TaxonomyLevel1 143 * <li>Event.TaxonomyLevel2 144 * <li>Event.TaxonomyLevel3 145 * <li>Event.TaxonomyLevel4 146 * <li>Event.XDASEventName 147 * <li>Event.XDASEventOutcome 148 * <li>Event.XDASRegistry 149 * <li>Event.XDASProvider 150 * <li>Event.XDASClass 151 * <li>Event.XDASIdentifier 152 * <li>Event.XDASOutcome 153 * <li>Event.XDASDetail 154 * </ul> 155 * @param {String} key The string to use as the taxonomy key 156 * @return {Boolean} Result 157 */ 158 Event.prototype.setTaxKey = function(key){ 159 // Use key to look up taxonomy 160 if (typeof key == "undefined") { return false; } 161 var taxonomy = instance.MAPS.tax.lookup(key); 162 if (typeof taxonomy == "undefined") { return false; } 163 this.TaxonomyLevel1 = taxonomy[0]; 164 this.TaxonomyLevel2 = taxonomy[1]; 165 this.TaxonomyLevel3 = taxonomy[2]; 166 this.TaxonomyLevel4 = taxonomy[3]; 167 this.XDASTaxonomyName = taxonomy[4]; 168 this.XDASOutcomeName = taxonomy[5]; 169 var taxcode = instance.MAPS.taxcode.lookup(this.XDASTaxonomyName); 170 var taxout = instance.MAPS.taxout.lookup(this.XDASOutcomeName); 171 this.XDASRegistry = taxcode[0]; 172 this.XDASProvider = taxcode[1]; 173 this.XDASClass = taxcode[2]; 174 this.XDASIdentifier = taxcode[3]; 175 this.XDASOutcome = taxout[0]; 176 this.XDASDetail = taxout[1]; 177 return true; 178 }; 179 180 /** 181 * Sends an event to the Collector Manager. 182 * This method consumes the input record object to set fields in the output event, 183 * as well as performing some additional processing. 184 * @param {DataMap} datamap The map to use (optional) when converting the 'rec' object into the Event. Will default to Rec2Evt. 185 * @return {Boolean} Result 186 */ 187 Event.prototype.send = function(datamap) { 188 189 if (typeof datamap == "undefined") { 190 datamap = instance.MAPS.Rec2Evt; 191 } 192 193 // Convert record to output event (if this is not an internal event) 194 if (typeof rec != "undefined") { 195 rec.convert(this, datamap); 196 } 197 else { // probably a debug event with no input record; need a blank one 198 rec = new Record(); 199 var hashMap = new HashMap(); 200 rec.connectorData = new ConnectorData(hashMap); 201 } 202 203 // Produce debug output 204 if (instance.CONFIG.params.ExecutionMode == "debug") { 205 instance.CONFIG.debugFile.writeLine(JSON.stringify(this) + "\n"); 206 } 207 208 // Mark replay events 209 if (rec.CONNECTION_MODE == "Replay") { 210 this.SensorType = "T"; 211 } 212 213 // resolve hostnames if asked 214 if (instance.CONFIG.params.Resolve_IP_and_Hostname == "yes") { 215 var assets = {"Init":null,"Target":null,"Observer":null,"Reporter":null}; 216 217 var unknownIPs = []; 218 var unknownHosts = []; 219 var fqdn; 220 221 for (var asset in assets) { 222 if (typeof this[asset + "HostName"] == 'undefined') { // Need the hostname 223 if (typeof this[asset + "IP"] != 'undefined') { 224 if (typeof instance.MAPS.ip2n[this[asset + "IP"]] != 'undefined') { 225 fqdn = instance.MAPS.ip2n[this[asset + "IP"]][0]; 226 if (fqdn.search(/\./) != -1) { 227 this[asset + "HostName"] = fqdn.substr(0, fqdn.indexOf(".")); 228 this[asset + "HostDomain"] = fqdn.substr(fqdn.indexOf(".") + 1); 229 } else { 230 this[asset + "HostName"] = fqdn; 231 } 232 } else { 233 unknownIPs.push(this[asset + "IP"]); 234 } 235 } 236 } else { // Need the IP 237 if (typeof this[asset + "IP"] == 'undefined') { 238 if (typeof this[asset + "HostName"] != 'undefined' && typeof this[asset + "HostDomain"] != 'undefined') { 239 fqdn = this[asset + "HostName"] + "." + this[asset + "HostDomain"]; 240 } else if (typeof this[asset + "HostName"] != 'undefined' && typeof this[asset + "HostDomain"] == 'undefined') { 241 fqdn = this[asset + "HostName"]; 242 } 243 if (typeof fqdn != 'undefined') { 244 if (typeof instance.MAPS.n2ip[fqdn] != 'undefined') { 245 this[asset + "IP"] = instance.MAPS.n2ip[fqdn][0]; 246 } else { 247 unknownHosts.push(fqdn); 248 } 249 } 250 } 251 } 252 } 253 254 if (unknownIPs.length > 0) { 255 var needIPsFile = new File(instance.CONFIG.commonDir + instance.UUID + ".needIPs.tmp", "w"); 256 for (var i = unknownIPs.length - 1; i > -1; i--) { 257 needIPsFile.writeLine(unknownIPs[i]); 258 } 259 needIPsFile.close(); 260 } 261 if (unknownHosts.length > 0) { 262 var needHostsFile = new File(instance.CONFIG.commonDir + instance.UUID + ".needHosts.tmp", "w"); 263 for (i = unknownHosts.length - 1; i > -1; i--) { 264 needHostsFile.writeLine(unknownHosts[i]); 265 } 266 needHostsFile.close(); 267 } 268 } // end name resolution 269 270 if (instance.CONFIG.params.Resolve_IP_To_User == "yes") { 271 // Store a user if they log in 272 if (this.XDASClass == "2" && this.XDASIdentifier == "0" && this.XDASOutcome == "0" && 273 (typeof this.TargetUserName != "undefined" || this.TargetUserName != "") && 274 (typeof this.TargetUserID != "undefined" || this.TargetUserID != "") && 275 typeof this.TargetIP != "undefined" && this.TargetIP != "") { 276 var ip2uFile = new File(instance.CONFIG.commonDir + instance.UUID + ".ip2u.tmp", "w"); 277 ip2uFile.writeLine(this.TargetIP + "," + this.TargetUserName + 278 "," + this.TargetUserDomain + "," + this.TargetUserID); 279 ip2uFile.close(); 280 } 281 // If InitUserName is unset, try to find it 282 if (typeof this.InitUserName == "undefined" && typeof this.InitUserID == "undefined" && 283 typeof this.InitIP != undefined && this.InitIP != "") { 284 var userinfo = instance.MAPS.ip2u.lookup[this.InitIP]; 285 if (typeof userinfo[0] != "undefined" && userinfo[0] != "") { 286 this.InitUserName = userinfo[0]; 287 } 288 if (typeof userinfo[1] != "undefined" && userinfo[1] != "") { 289 this.InitUserDomain = userinfo[1]; 290 } 291 if (typeof userinfo[2] != "undefined" && userinfo[2] != "") { 292 this.InitUserID = userinfo[2]; 293 } 294 } 295 } // end user resolution 296 297 // Construct the Java event from the JS event 298 var JEvent = new EventData(); 299 for (var field in this) { 300 if (this.hasOwnProperty(field)) { 301 var value = this[field]; 302 if (value != "" && instance.MAPS.Evt2EvtData[field] && typeof value != "undefined" && value != "undefined" 303 && field != "DeviceEventTime" && field != "BeginTime" && field != "EndTime") { 304 JEvent.setString(instance.MAPS.Evt2EvtData[field], String(value)); 305 } 306 } 307 } 308 309 // Set DeviceEventTime and DeviceEventTimeString 310 if (this.DeviceEventTime instanceof Date) { 311 this.DeviceEventTime.adjustTimezone(); 312 JEvent.setDeviceEventTime(String(this.DeviceEventTime.getTime())); 313 JEvent.setString( "et", this.DeviceEventTime.toString()); 314 } 315 316 // Set BeginTime and EndTime 317 if (this.BeginTime instanceof Date) { 318 this.BeginTime.adjustTimezone(); 319 JEvent.setString("bgnt", String(this.BeginTime.getTime())); 320 } 321 if (this.EndTime instanceof Date) { 322 this.EndTime.adjustTimezone(); 323 JEvent.setString("endt", String(this.EndTime.getTime())); 324 } 325 // Send event 326 instance.CONFIG.scriptContext.fireEvent(JEvent, rec.connectorData); 327 return true; 328 }; 329