Tuesday, March 9, 2010

The ORACLE_HOME does not contain Java.

While trying to install Oracle's Configuration Manager application, I ran in to the following error:

The ORACLE_HOME does not contain java.
The ORACLE_HOME does not contain a valid JDK/JRE.

This particular tier did not have Java installed, so that it was complaining was expected. However, I didn't want to install Java on this tier just to get CCR. I opened up the setup script to see what it was doing. Upon doing so, I found that it was referencing JAVA_HOME_CCR. Setting this to the path of Java fixed the issue and setup continued normally.

export JAVA_HOME_CCR=/u01/DEV/devcomn/util/java/1.4/j2sdk1.4.2_04

It appears that you only need to configure this for the setup. I've rebooted my server several times and emCCR continues to show that it is running and working correctly.

Monday, November 23, 2009

IIS Admin Scripts (adsutil.vbs, stopweb.vbs, contsrv.vbs, etc)

Typically when I do an install of IIS, I delete everything out of the root folder or I move it. The other day, I was in need of adsutil to increase the max connections on an install I was doing. Since I had deleted the scripts earlier, I looked around the web to find them, but nobody had that file. Lots of articles talking about it and how to use it. Nobody had it though.

So I've gone and made them available. I found a copy on my XP virtual server. The zip file contains the following:


  • adsutil.vbs

  • chaccess.vbs

  • contsrv.vbs

  • contweb.vbs

  • dispnode.vbs

  • disptree.vbs

  • findweb.vbs

  • mkwebdir.vbs

  • pausesrv.vbs

  • pauseweb.vbs

  • startsrv.vbs

  • startweb.vbs

  • stopsrv.vbs

  • stopweb.vbs

  • synciwam.vbs



As I mentioned, these are straight from an XP install. It's everything that was in the admin scripts folder.

Tuesday, November 10, 2009

Could not load file or assembly 'app_code'

Most (if not all) of the stuff I post on this blog is about errors I have come across that took me more than a few minutes to solve. This is another of those. A web application I installed was throwing this odd error message:

Could not load file or assembly 'app_code' or one of its dependencies. Access is denied.


The strange thing was that this was a precompiled .Net (3.5) application. It didn't need app_code, and I wasn't sure why on earth it was trying to access a folder that didn't exist. I searched web.config for references to it and found nothing. I even created the folder to see what it would do, but it didn't like that either.

This server it was installed on has been behaving badly. After some poking around, I discovered that the root folder for the website didn't have two key permissions, "ASPNET" and "Network Service". I added both with read permissions and the problem went away. Now, I don't know which one fixed it, and since I was pressed for time to bring the site up, I left both of them. In hindsight, I should have removed each of them one at a time to find which fixed the problem (or if they were both needed).

Anyway, long story short, adding those two to the security of the root folder fixed the problem. It actually complained about not needing app_code for a precompiled application, so I removed the folder I had created to find the problem and suddenly the site was working again.

Wednesday, October 28, 2009

Bulk loading in Oracle - %ROWTYPE and %TYPE

I decided to finally jump in to doing some bulk loading in Oracle a bit ago and ran in to a weird problem with dbms_output.put_line. Basically it was complaining that I was passing the wrong arguments to put_line. I searched around on Google for help, and found quite a bit on bulk loading, but none seemed to address the problem I was having. Basically, how to reference the actual data.

My original code was using %ROWTYPE, but all the examples I could find were sending that collection off to another procedure. That procedure wasn't outlined anywhere, so I had no idea how they were displaying the data. Below are two different PL/SQL scripts. The first uses %ROWTYPE and the second uses %TYPE. Both have a working dbms_output.put_line so you can see how to reference the data.

The data is from two different tables, ticket_headers_all and user_settings. The first table is just a ticket system containing a header_id, summary, and a few other fields. The user_settings table has a user_id and some other fields. If requested, I'll move these over to the familiar EMP/DEPT schemas instead.

%ROWTYPE

DECLARE
-- Create the container for our data
TYPE tickets_att IS TABLE OF ticket_headers_all%ROWTYPE
INDEX BY binary_integer;

-- And create a variable of the container type
l_tickets tickets_att;

BEGIN
-- First we load the collection. Consider LIMIT if you have a lot of data.
SELECT * BULK COLLECT INTO l_tickets
FROM ticket_headers_all;

FOR ticket_index IN l_tickets.first .. l_tickets.last
LOOP
-- Output the summary field
dbms_output.put_line(l_tickets(ticket_index).summary);
END LOOP;
END;


%TYPE

DECLARE
-- Declare the collection
TYPE users_att IS TABLE OF user_settings.user_id%TYPE
INDEX BY binary_integer;

-- Declare a variable of the collection type
l_users users_att;

BEGIN
SELECT user_id BULK COLLECT INTO l_users
FROM user_settings;

FOR user_index IN l_users.first .. l_users.last
LOOP
-- Print all the user_ids
dbms_output.put_line(l_users(user_index));
END LOOP;
END;


Catches
There are a few things to be aware of. These statements will throw an exception if there are no results. You can get around this pretty easily by adding an if clause around the FOR loops to check the count. For example, if(user_index.Count > 0). There are also different types of loops that you can use, some better than others depending on your data.

As alluded to in the comment, you should consider using LIMIT to restrict how much memory is used by your bulk collect. Without a limit, it's going to use as much memory as it can. With a small table, this may not be a big issue for you, but tables do grow so you should include a default size (like 1000 rows).

Hopefully this helps some of you. It's a very basic problem and easy to fix, but if you don't know what to search for, it can be hard to figure out why put_line is throwing an error. As to the cause of the error itself? put_line doesn't handle a row of data, which is what I was sending it. Woops.

Wednesday, September 9, 2009

Oracle JInitiator, Internet Explorer 8, and Data Execute Prevention

Our company recently pushed out the IE8 update to our users after various users tested it without any issues. The following day, our Oracle users were unable to access our Oracle ERP system. At the point where JInitiator is launched, IE8 would simply close down with the following error:

"Data Execute Prevention - To help protect your computer, Windows has closed this program."


Not too kind of it. We tried the usual fixes; disabling addons, messing with anti-virus, uninstalling programs. Nothing seemed to fix it. And then I stumbled on to this setting in IE8, "Enable memory protection to help mitigate online attacks". As much as I believe the ERP system to be an attack some days, it was that setting that was killing JInitiator. Unchecking the checkbox and restarting IE fixed the problem. You can find it at:

Tools -> Advanced Tab -> Scroll all the way down to the security area and look for "Enable memory protection to help mitigate online attacks".


Hope this helps some of you looking for a solution to this problem. Sadly I'm sure that checkbox is there for a good reason, such as mitigating online attacks. Oracle just doesn't play well with it yet (at least our version doesn't).

Monday, August 10, 2009

[Windows] Automatically banning an IP address in IIS FTP

(Reposted from my mscorlib blog)
We've been having a horrible time with zombie attacks against our IIS FTP server for a long time now. Almost every Saturday night, like clockwork, they start their attack. They attempt to log in with names that systems may use: administrator, oracle, mysql, admin, etc. I don't care much since those accounts don't even exist. I just get annoyed with seeing them in my log files and filling up my event log. Up until today, I have been banning the IP addresses by hand. No more.

I had 100 megs in log files over the weekend. That was the last straw. After quite a bit of searching and messing around, I found a script to solve my problems. Below is a step-by-step walkthrough on how to set this script to run as a service.

The following is how I solved this problem on our Windows 2003 server (running the Web edition of Win2k3).

First off, you need to grab the script file from the aforementioned site (blog.netnerds.net) and stick it on your server. Mine is in c:\scripts. I named it BanIP.vbs before I realized there was a button on the site to download it as banftpips.vbs.

Next, you'll need two files from the MS resource kit, Srvany.exe and Instsrv.exe. You can get it from Microsoft. Download the executable and run it on your work computer or dev box. You just need the two files mentioned above, not the whole thing. Stick these two files in the same spot as the script to make it easier.

Open up a command prompt and change to the scripts directory. Enter the following command to register srvany as a service:

C:\Scripts\instsrv.exe BanIP C:\Scripts\Srvany.exe

This will create a registry setting. Use regedit to open up the following key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BanIP

Create a new key and call it Parameters

In the Parameters key, create a new String Value called Application. Set the value of Application to:

C:\Windows\System32\CScript.exe C:\Scripts\BanIP.vbs

Open up your services. You should see BanIP there. Click the start icon if it's not already going. Using a separate computer to test with, hit your ftp site and try to log in as administrator with a bad password. I can't stress enough, use a different computer than your primary box. The IP address will be banned for the entire site. You can see the ban under the routing tables by using 'route print' at the command prompt. You can delete the route with 'route delete '. There is also a new entry in the FTP security settings.

It's a great script, and fairly easy to modify. For more help on the script itself, check out the site and read the comments. Lots of good stuff there. Special thanks to the author, Chrissy. This will surely slow down our zombie problems.

Comments from mscorlib
You can set the service to start manually (or disable it). That will stop it. To clean it up, you'll need to use the 'route' command to remove the entries it made, as well as cleaning up the IIS FTP security stuff (where it blocks the IP addresses). Make sure you move the log files somewhere else first, however, since the script will look at the log files and reban the IP address if it sees it again (this caused me some headaches originally since I didn't know it did that).

I've been running it now since I posted this article, and the attempts at breaking in are way down. The routes look like they reset eventually, either via an update we did, or something else, but the IIS settings are still there. Our log files are much smaller, and I don't have to constantly check the site to see if someone is breaking in. I set it up to run off of several keywords and haven't had any problems.


I _think_ this is how it's working... like I mentioned, the actual script isn't mine. But basically the first spot you see that, it triggers the code that scans the log files (according to the notes at the very top of the script). The second spot is where it is actually looking for the usernames to ban. I put admin and administrator in the first spot:

If InStr(LCase(objObject.TargetInstance.Message),"administrator") > 0 OR InStr(LCase(objObject.TargetInstance.Message),"admin") > 0 Then

And in the second spot I put the rest of the keywords:

If sUsername = "administrator" OR sUsername = "mysql" OR sUsername = "admin" Then

So basically, if they do admin/administrator, it will trigger the log scanning, which will also ban any attempts at 'mysql'. But mysql will not trigger the script. Since admin/administrator were the two largest failed attempts, I used those to set things off. If we had more, I'd probably throw them in to both places just to be safe. If you have a massive list, you may want to consider using an array or just a delimited string and using instr on it. Might be easier to maintain.


http://blog.integrii.net/?p=18 - I created a remote installer (including registry entries) using psexec. This automates your whole process with a little tuning! Email me for blog link exchange! (I removed his email address to reduce his spam)



[C#] DayOfWeek as numeric

(Reposted from my mscorlib blog)

I'm writing a timecard program for our workplace. I was trying to get the day of the week as a number (today being Friday, I was looking for a '5'). I couldn't find much info on Google, aside from some article talking about something unrelated. I saw a snippit of code there. Too easy, I thought:

int dayofweek = (int)DateTime.Now.DayOfWeek;

And that's it. *slaps forehead* I suppose I should have tried that first since it's a two-second check. Oh well. Since I was searching Google without much luck, I hope to get this out there so others might see it.

As for finding a specific day of the week, I went with this for now:

int dayofweek = (int)DateTime.Now.DayOfWeek;
int offset = 0;
DateTime thisFriday;

if (dayofweek < 5)
offset = 5 - dayofweek;
else
offset = dayofweek - 5;
thisFriday = DateTime.Now.AddDays(offset);

I spent about 5 minutes doing that. It calculates when the next upcoming Friday is (if the current date is Friday, then it shows that). I've set it in to a for loop to spit out a month of Fridays by combining it with AddDays. As always, let me know if there's a better way.

Comments from mscorlib
I resolve with

(Int32)Enum.Parse(typeof(DayOfWeek), dpartenza.DayOfWeek.ToString())