001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.transaction; 020 021import org.jpos.core.Configurable; 022import org.jpos.core.Configuration; 023import org.jpos.core.ConfigurationException; 024import org.jpos.iso.ISOException; 025import org.jpos.iso.ISOMsg; 026import org.jpos.iso.ISOUtil; 027import org.jpos.tlv.TLVList; 028import org.jpos.util.FSDMsg; 029import org.jpos.util.ProtectedLogListener; 030 031import java.io.Serializable; 032 033/** 034 * @author Alejandro Revilla 035 * @author David Bergert 036 * @author Barspi 037 */ 038 039/** 040 *Sample Usage: 041 *<pre> 042 * <participant class="org.jpos.transaction.ProtectDebugInfo" logger="Q2" realm="debug"> 043 * 044 * <property name="protect-entry" value="REQUEST" /> 045 * <property name="protect-entry" value="RESPONSE" /> 046 * <property name="protect-entry" value="PAN" /> 047 * <property name="protect-entry" value="REQUEST_ICC_DATA" /> 048 * 049 * <property name="wipe-entry" value="EXPDATE" /> 050 * 051 * <property name="protect-ISOMsg" value="2" /> 052 * <property name="protect-ISOMsg" value="35" /> 053 * <property name="protect-ISOMsg" value="45" /> 054 * <property name="wipe-ISOMsg" value="52" /> 055 * <property name="wipe-ISOMsg" value="55" /> 056 * 057 * <property name="wipe-TLVList" value="0x56" /> 058 * <property name="wipe-TLVList" value="0x57" /> 059 * <property name="wipe-TLVList" value="0x5a" /> 060 * <property name="wipe-TLVList" value="0x5f20" /> 061 * 062 * <property name="protect-FSDMsg" value="account-number" /> 063 * <property name="protect-FSDMsg" value="track2-data" /> 064 * 065 * </participant> 066 *</pre> 067 **/ 068 069 public class ProtectDebugInfo implements AbortParticipant, Configurable { 070 private String[] protectedEntries; 071 private String[] wipedEntries; 072 private String[] protectFSD; 073 private String[] protectISO; 074 private String[] wipeISO; 075 private String[] wipeTLV; 076 077 public int prepare (long id, Serializable o) { 078 return PREPARED | READONLY; 079 } 080 public int prepareForAbort (long id, Serializable o) { 081 return PREPARED | READONLY; 082 } 083 public void commit (long id, Serializable o) { 084 protect ((Context) o); 085 } 086 public void abort (long id, Serializable o) { 087 protect ((Context) o); 088 } 089 private void protect (Context ctx) { 090 /* wipe by removing entries from the context */ 091 for (String s: wipedEntries) 092 ctx.remove(s); 093 /* Protect entry items */ 094 for (String s: protectedEntries) { 095 Object o = ctx.get (s); 096 if (o instanceof ISOMsg){ 097 ISOMsg m = ctx.get (s); 098 if (m != null) { 099 m = (ISOMsg) m.clone(); 100 ctx.put (s, m); // place a clone in the context 101 for (String p: protectISO) 102 protectField(m,p); 103 for (String p: wipeISO) 104 wipeField(m,p); 105 } 106 } 107 if (o instanceof FSDMsg){ 108 FSDMsg m = ctx.get (s); 109 if (m != null) { 110 for (String p: protectFSD) 111 protectField(m,p); 112 } 113 } 114 if (o instanceof String){ 115 String p = ctx.get(s); 116 if (p != null){ 117 ctx.put(s, protect (p)); 118 } 119 } 120 if (o instanceof TLVList) { 121 TLVList tlv = ctx.get(s); 122 if (tlv != null) { 123 for (String t: wipeTLV) 124 wipeTag(tlv, t); 125 } 126 } 127 } 128 } 129 private void protectField (ISOMsg m, String f) { 130 if (m != null) { 131 m.set (f, protect (m.getString (f))); 132 } 133 } 134 private void wipeField (ISOMsg m, String f) { 135 if (m != null) { 136 Object v = null; 137 try { 138 v = m.getValue(f); 139 if (v != null) { 140 if (v instanceof String) 141 m.set(f, ProtectedLogListener.WIPED); 142 else 143 m.set(f, ProtectedLogListener.BINARY_WIPED); 144 } 145 } catch (ISOException ignored) { 146 //ignore, valid routes for some messages in the context may not be vaild for others 147 //e.g. in transaction switches with protocol conversion 148 } 149 } 150 } 151 152 static void wipeTag(TLVList tlv, String tag) { 153 if (tlv == null) 154 return; 155 try { 156 int tagName = Integer.decode(tag); 157 if (tlv.hasTag(tagName)) { 158 tlv.deleteByTag(tagName); 159 tlv.append(tagName, ProtectedLogListener.BINARY_WIPED); 160 } 161 } 162 catch (Throwable ignored) { } 163 } 164 165 private void protectField (FSDMsg m, String f) { 166 if (f != null) { 167 String s = m.get (f); 168 if (s != null) 169 m.set (f, ISOUtil.protect (s)); 170 } 171 } 172 private void wipeField (FSDMsg m, String f) { 173 if (m != null && m.get(f) != null) { 174 m.set (f, "*"); 175 } 176 } 177 private String protect (String s) { 178 return s != null ? ISOUtil.protect (s) : s; 179 } 180 public void setConfiguration (Configuration cfg) throws ConfigurationException { 181 this.protectedEntries = cfg.getAll("protect-entry"); 182 this.wipedEntries = cfg.getAll("wipe-entry"); 183 this.protectFSD = cfg.getAll("protect-FSDMsg"); 184 this.protectISO = cfg.getAll("protect-ISOMsg"); 185 this.wipeISO = cfg.getAll("wipe-ISOMsg"); 186 this.wipeTLV = cfg.getAll("wipe-TLVList"); 187 } 188}