Java Security FUD

As soon as Java started to grow in popularity, the misinformation about it began to spread. There are, of course, a number of legitimate criticisms of Java, but most of them have been used constructively to improve it. One of the oldest criticisms of Java was that it is slow - a criticism that was valid once-upon-a-time, but has become decreasingly relevant as Sun has made improvements to the JVM (particularly with Just-In-Time compilation). My friend Brandon has thoroughly deflated this criticism in a blog post that grew into a JDJ article (congrats, Brandon!), so I won't spend any more time on it.

A great deal of the invalid criticism of Java actually comes from a misunderstanding of the purpose of Java. Though the goals of Java have certainly changed since it was conceived as an embedded systems language to run appliances, there is no denying that, currently, the goals of Java are clear: write once, run anywhere. Though there are a number of areas Java stands to improve on this goal, it is definitely the idea. This inherently means that Java applications don't get to access low-level system calls that bypass the JVM. This limitation is the core cause of the common criticism that Java doesn't give you enough rope to hang yourself, as C++ does.

I am unsure of what it is about Java that inspires such a dogmatic loathing of it by so many developers that prefer not to use it. Though dogmatism is no stranger to the world of software development, it rarely reaches the level of vitriol that is common in the "Java vs. Anything" debate.

One such example is a web site entitled "Sun Redefines Randomness". The wording of even the title of this page makes it clear that its contents are meant as a criticism against Sun and Java, but unsurprisingly a bit of investigation reveals that it is simply FUD.

The page contains a simple applet. This applet generates a field of black and white boxes, using the java.util.Random class and taking the lowest-order bit from each integer generated to decide the color of the box. It does this repeatedly in an animation, and there is no denying that when you look at the applet's output, there is a distinct pattern to it. From the page:

As you can probably see by the horizontal stripes, this 'random' method exibits significant periodic behavoiour.

Rather than looking like random static, the applet's display looks like a badly tuned-in television.

All Java virtual machines that are available to me appear to exhibit the same problem.

It is interesting, his point about how all virtual machines do this. Of course they do - the implementation of Random is in the actual class file, not the JVM.

In any case, the author of this page doesn't seem to understand a few basic things about java.util.Random. This isn't surprising, since these things aren't exactly well-documented or obviously apparent.

RNGs

Random Number Generators (RNGs) are not, generally speaking, actually random. Picking a random number is actually a relatively difficult task, which is why random number generators pick what are called "pseudorandom" numbers.

With computers, it is not simply enough to use the last digit of the computer clock whenever you need a random number. There are actually patterns to when the OS schedules your process to run, and those patterns emerge when you try such a thing, but that's not the point. Random Number Generators need to run from a seed, meaning that you need to supply the RNG with a starting number, and it needs to generate a sequence of numbers based on that starting number. If you were to give an RNG the same seed again, it would need to generate the same sequence of pseudorandom numbers. Why bother with the seed? Because without it, you might not be able to easily reproduce a bug in your program consistently, which means you can't fix it. Being able to make the computer go through the same sequence of events is requisite for consistent debugging, which means even if you use random numbers in your program you must be able to get to the same sequence of random numbers.

This means that every RNG needs to work by performing a series of mathematical operations on a number. The RNG starts with a seed, and performs a series of mathematical operations on it to get the first "random" number. The next time a random number is needed, it performs the same operations on the last random number to get a new one, and so on. This ensures that, given the same starting number (the seed) the same sequence of numbers would be generated.

As you might imagine, a very bad random number generator would likely reveal a predictable pattern, given these constraints. So, is Java's RNG bad?

Java's Random class

When it was time to write a RNG for Java, a decision had to be made. Typically, when programmers use a random number generator they just want, effectively, a dice-roller. It is rarely important that a sequence of a million dice rolls generated in this manner not reveal a pattern. It is far more important, to your TYPICAL development purpose, that the dice-rolls occur quickly. Secondarily, it is important that the dice-rolls be fair, meaning that if you were using an RNG to generate a random number from 1-6, you would get an even distribution for each number approximately 1/6th of the time. Thirdly, it is important that the numbers be non-periodic, which is to say lacking predictable patterns in number generation.

There are a LOT of algorithms to take a number and generate a new pseudorandom number based on it. Most of these algorithms work by (and this is a gross oversimplification) multiplying the number by an extremely large number in order to put it far outside of the range of desired numbers, then adding another offset number, and then modding that number to get it back into the range. This is called a "linear congruential algorithm".

Java's Random class uses a 48-bit version of this algorithm. Here is the entire code that does the work of turning a number into the next number in the sequence:

seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);

Just as described, this algorithm multiplies the previous number (seed), adds another number, then munges it back within range.

As you can imagine, because of the small number of mathematical operations, this algorithm is extremely fast. The constants used here have been selected because they yield random numbers that are fair.

Could the algorithm have also been non-periodic? Yes, but it would also be slower. Sun selected an algorithm that, first and foremost, is quick. They made this call based on their best guess for what your average developer using the class needed. Had they made it more cryptographically secure (more "random") it would have been slower.

Java's SecureRandom class

Of course, there ARE people who need numbers that are more cryptographically random. Sun made the logical choice: extend the Random class into a new class that overrides the generating function. Inside of the java.security package is a class called SecureRandom that has the same methods as Random. It re-implements the main seed-modifying method to use a completely different algorithm.

In fact, you can supply a number of options to the constructor of SecureRandom to use a variety of different popular random number generating algorithms. If you supply no arguments, SecureRandom will be constructed with the best generator it can find.

The author's source code is located here. If you simply change the code to construct an instance of java.security.SecureRandom rather than java.util.Random, without changing a single line of code otherwise, the pattern in the graph instantly vanishes.

On line 37, I have changed

Random rnd = new Random();

to

Random rnd = new java.security.SecureRandom();

I have uploaded the changed version here.

There are two things worth noticing about this new version of the applet. One, it lacks the periodicity illustrated in the non-secure applet. Two, the framerate is much lower.

Like I said, Random was written to be fast, which it is. SecureRandom is designed to be secure, so it is much slower.

Long story short, if you are writing code that needs somewhat random numbers and needs them quickly, use java.util.Random. If you are writing code that needs extremely random numbers less quickly, use java.security.SecureRandom. Of course, if you are writing code that needs extremely random numbers extremely quickly, use a degree in mathematics.

As you can see, this is just another unwarranted criticism of Java that is as trivial as it is un-researched. Criticism is meant to be constructive, which means it is meant to help a thing improve. It is impossible to improve upon something that isn't actually broken, so this kind of FUD accomplishes little more than further polarizing the world of software development.

Responsibility Of Data Warehouses

Imagine that you are going on a long vacation, and you ask a good friend to take care of your cat while you're away. Your cat seems pretty content with your home, so you give your friend the key to your apartment so he can come over once every few days and refill the water bowl, empty litter, etc.

One day, though, your friend forgets to lock your front door when he leaves. The next day, someone enters your home and steals your television, your jewelry, your computer, and everything else of value.

Who is to blame?

Obviously, we blame the robber. But do we blame the friend? I think most of us would blame the friend, as it was his responsibility to lock the door, and it was this failure to do so that caused your items to be stolen. We may feel a bit bad yelling at this friend (since we asked him to come over) but in the end we would still blame him.

Watch how this problem changes when you catch the robber, though. Right now, if you imagine yourself in this scenario, you're angry with your friend. Change the scenario to imagine the robber is caught the next day and all of your stuff is returned. Now, likely, you're angry with the robber. You don't feel any animosity toward the friend at all, yet his role in this is completely unchanged. He still should have locked the door, he still failed to do so, and he still allowed a stranger into your home as a result. Why are we less angry with him in this scenario? It is not because he is less responsible, but because we now have someone else to be more angry with. The robber is the MOST responsible person for the robbery, your friend a close second. Because of this, when you can hold the most responsible person accountable, you are likely to ignore the role played by the next-most-responsible individual.

Next time you go on vacation, however, you are likely to not ask this same friend to take care of your cat, because you still know he is partially responsible for this security breach.

Data Warehouses

Let's change the scenario one more time. Instead of a friend, imagine the person in your home has not been invited. Imagine that the way things really work is that, whenever you buy a home, or a car, or a television, or even a pizza, you have to pay with money as well as part of your housekey. It's not the whole housekey, but it's a chunk of the housekey - and each purchase requires a different chunk of the key. You are trusting every company you make a purchase from in this way not to do anything with the portion of the key, but you're not too worried; after all, it's only part of the key.

Then all of those companies turn around make a copy of your portion of the key, then send the portion to another company, which we'll call Acxiom. Eventually Acxiom collects enough portions of your key that they can form your entire housekey, which they then use to enter your home when you aren't there. They don't steal anything or take anything, but they do take notice of your home, your car, your television, and your empty pizza boxes.

This allows them to figure out what kind of thing you might be likely to buy next if asked. In your case, based on the stuff in your house, it seems likely that you'd be willing to purchase a DVD Player if given a little push. Acxiom then tells Sony that you might want to buy a DVD Player, Sony pays them money to do so (giving Acxiom profit enough to keep collecting portions of housekeys) and then sends you a DVD Player catalog, or calls you on the phone to tell you about a great deal, or sends you an e-mail.

Now, I don't want to get into how annoying this entire business model is, or how Acxiom has no right to be entering your home, even if you had to give portions of housekeys to everyone from whom you made a purchase. This post is not about how a company that does this shouldn't exist.

This post is about what happens when that company leaves your door unlocked.

Responsibility

Surely in this scenario, if Acxiom left your door unlocked, you would find Acxiom completely responsible. After all, who the hell invited them in the first place?

ChoicePoint (Acxiom's major competitor) had a data breach not too long ago, and it was held responsible and fined. Only a portion of the fine was actually given to the victims of the data breach (people whose identities were stolen), but the fine was still large. We also hold the robber responsible in these cases, but we do not allow the responsibility of the robber to overshadow the responsibility of the person who left the door unlocked. If anything, because we are placing so much trust in these kinds of companies, we hold the data company more responsible than the attacker.

To that point, ChoicePoint was fined $15 million, and the attacker sentenced to 16 months in prison.

Clearly we, as a society, said to ChoicePoint, "look, we aren't huge fans of you holding on to all of this data, but if you're going to do so, you had better damn well protect it." ChoicePoint is responsible for the theft of its data, and we have sent them that message loud and clear, to the tune of 15 million dollars. ChoicePoint invested tons of money in improving their security as a result.

If you hold data and do not protect it adequately, it is your fault when it is stolen.

Acxiom's Breach

A few years ago, a man who had legitimate access to part of Acxiom's data broke into other Acxiom databases and gained access to a lot of information about various people. He then sold some of this information to advertisers so they could launch an ad campaign using it.

He was caught, and much like when the robber was caught in the first scenario, that seemed to overshadow the fact that the breach happened in the first place.

The article explains:

Prosecutors said Levine had permission to access part of Acxiom's database but that he used decryption software to obtain passwords and go beyond his authorized access. Data stolen included names, telephone numbers, street addresses and e-mail addresses, along with highly detailed demographic information.

If Levine used "decryption software to obtain passwords" to other databases, it means that the passwords were, first, stored in a place that they could be retrieved without authorization to do so and, second, were stored in a cryptographically reversible manner. Passwords are usually stored as a one-way hash. You type your password to be saved, and the software hashes it into a special code. This code cannot be reversed to get back to the original password, but every time the password is hashed it yields the same code. Next time you try to verify your identity, the software performs the same hash and compares the hash codes. If they are equal, you must have typed the correct password.

If an attacker gets access to these hash codes, they cannot reverse them to get back to the password. This article indicates Levine did so, which indicates that the passwords we being stored in a way that allowed them to be decrypted. This was Acxiom's mistake - they should not have stored passwords in this manner.

Moreover, they should have had better access control, so that people with access to part of the system wouldn't be able to access a different part of the system.

These are both failures on the part of Acxiom to protect your data, yet the person being held fully responsible is Levine. As a matter of fact, Levine has to pay $153,395 to Acxiom, so they are actually being rewarded for failing to secure your data. Why?

Why did the government hold ChoicePoint responsible for a similar breach, but only hold the attacker responsible when it happens to Acxiom? On what grounds have we decided Acxiom has done nothing wrong?

They left the door unlocked.

Saying Goodbye To Windows

I've been a lifelong Windows user. The first computer I ever had ran Windows 3.1 and I eagerly upgraded to Windows 95, 98, and 2000. I considered myself a power user of these operating systems. Yes, I ran Windows, but I also developed in Windows frequently, and I understood Windows at an accomplished level.

Though I've been an Open-Source advocate for quite some time, I frequently experienced major problems when trying out Linux.

I tried a version of RedHat when I was in high school, and I tried Mandrake, Gentoo, and Fedora when I was in college. Whenever I tried to use Linux, I was met with some kind of problem that I couldn't overcome by myself. A "deal-breaker", as I called it, that left me to transition back to Windows with frustration.

I lived on the Computer Interest Floor when I was in college, and a lot of my friends ran Linux, so I figured it would be a great time to evaluate Linux. I tried many times to run Linux with the help of these friends, but even they, as Linux Gurus, discovered my problems couldn't be overcome. I used my computer for everything - work, school, multimedia, and even television. Not being able to do my job (which was writing Flash applications) was a dealbreaker one year. Not being able to use my tv-card in Linux was a dealbreaker another year.

Despite being a huge fan of open-source as a philosophy, Linux was always not quite ready for me as a user. By the time I had "given up" on Linux, I was running Windows 2000 exclusively (I liked 2000 a lot more than XP, which I found obnoxious). Every machine I set up ran Windows 2000. I replaced the shell with the open-source LiteStep and a custom theme I wrote. I replaced the file manager with the freeware x2explorer. I ran OpenOffice rather than MS Office, and FireFox rather than IE. I liked joking that the only part of Windows I used was the kernel - everything on top of it was free, and usually open.

A year or so ago, when I started reading about Vista, I knew I was in for trouble. I resisted XP because I didn't like the direction it took, and Vista seemed even worse. DRM drivers, "call-home" spyware, and a general lack of control in the hands of users all really irked me. I kept reading articles about planned features for Vista, and eventually I discovered something that was new to me.

A dealbreaker. In Windows. At first I tried to convince myself that it was just a rumor, but as more articles were published it became clear that there was no way around it. Windows Vista binds itself to your computer hardware. If I install Windows Vista on a certain machine, then decide to replace the motherboard in that machine, Vista considers that to be a "new" computer. Despite the fact that the "old computer" is just a scrapped motherboard sitting in a box in my closet, and despite the fact that the hard drive upon which Vista was installed remains, Vista considers it a brand new computer.

They give you the first "new computer" categorized in this manner a free pass. Upgrade the motherboard again, however, and you need to buy a new copy of Vista.

My main desktop, which I call "wrath" has been my main desktop for many years. It has run Windows 2000 as long as it has existed, and it has been through at least 5 motherboards, 10 hard drives, 10 ram sticks, 3 cases, and 3 video cards. The hardware has changed regularly, but I always considered it the same machine, because it was my ONLY desktop machine and the components that made up my previous desktop went into a box in the closet. This means that the copy of Windows 2000 I purchased for use as my desktop OS has always been active on only one machine. This is a legitimate use of my Windows 2000 CD, well within legality and with a clear intention NOT to unfairly pirate the OS in any way. Yet, as of Vista, I would have needed to buy 2 or 3 copies of Vista for this. That's simply unacceptable. That's a dealbreaker.

As the days ticked by, they approached two important dates: the day of release for Windows Vista and the official day that Windows 2000 would stop being supported. No more patches, no more security upgrades for 2000 users. I was a Windows fan, but I'm not stupid: running Windows without security patches is technological suicide. I could buy myself some time by biting the bullet and upgrading to XP, but that wasn't really a permanent solution. I absolutely would never be willing to install Vista, so I had to come up with a way to continue using my computer in spite of that. It was time to return to my old rival, Linux.

About 8 months ago, I began a process of migrating to Linux. This was not my usual "install Linux and see how I like it" process - this was a full-on switch, with the intention of being permanent. When the process was complete, I'd be using Linux as my main desktop operating system. I was out of options for Windows, so I was embracing Linux entirely.

I needed to be competent with Linux by the time Vista came out. That meant no copping-out and dual-booting, and it meant not building a spare Linux box to "play around with". I had to immerse myself in Linux if I were going to really learn it.

Instead, I would build a spare Windows box to "play around with" so that I could continue running games and video editing tools. I did all of my multimedia tv-watching on an XP Box in the living room, so I wouldn't have to depend on Linux for that (since it has always given me trouble). With my requirements from my desktop machine relaxed, I had a much better chance of being successful with Linux.

It took some time to get the multimedia box stable, the windows machine built, and a network-storage solution enabled in my home so I could share things like music across my network. I was able to finally switch to Ubuntu Linux about 3 months ago.

How has it been?

Getting my mouse to work correctly has been a pain. Making Ubuntu play nicely with my Western Digital NetCenter was something of a nightmare. Linux can't seem to handle my KVM switch without disabling my mouse wheel. Every torrent app for Linux is inferior to uTorrent. I've definitely dealt with a lot of frustration in Ubuntu - frustration with things that I took for granted when I used Windows. Despite these frustrations, there has been a noticeable lack of something important: a dealbreaker.

As obnoxious as Ubuntu can be at times, nothing so far has made me give up and re-install Windows. Nothing has gone past the level of annoyance.

This week Vista was released to the world. Linux has no dealbreakers, only annoyances. Windows has a dealbreaker. For the first time since I started using a computer, the roles of Linux and Windows have switched for me. I've enjoyed Ubuntu so much that I'm considering installing it on my laptop.

Have I learned enough about Linux to consider myself "competent" with it in time for Vista's release? Not as much as I'd like, but I'm quick enough performing tasks in Linux that I feel like I've moved past the hardest part of the learning curve. By the time XP stops being patched, I think I will be comfortable enough with Linux to put it on my multimedia machine. By the time Windows 2000 stops being supported, I think I'll be okay with the idea of shutting down my backup Windows machine permanently.

A new version of Windows is out, and for the first time I don't care.

I'm a Linux User now.

Remote IFrame Detector

I saw a presentation yesterday about cross-site scripting. It was pretty interesting (though a bit overdramatic) but ultimately almost all of the attacks came down to the ability to send the user to a site which contains an iframe for the site they wanted to visit.

This allows the attacker to be running javascript code on their machine, but the iframe makes the user believe he or she is at the same site. This can allow for keylogging and some degree of remote control.

All of this hinges on the ability to load the real site in an iframe from within the hacker site. It seems to be that all you need to do is prevent an iframe from loading a page on a different host than the one containing the iframe.

A simple way to accomplish a task like this is to load a greasemonkey script that draws a border around any iframe that is at a different location than the parent site. Having never written a greasemonkey script before, I set about doing this.

This is my first greasemonkey script, so it likely sucks, but it seems to work on the very limited set of tests I performed.

To install the script, click here.

Constructive feedback and criticisms welcome. I'm happy to improve this script, though I may not know exactly how to do so. ;)

Bigger and Better Things…

Right after I graduated, I decided I needed a change of scenery and decided to move from New York to Colorado. I assumed that a Computer Science degree would get me a job pretty quickly after I graduated, so I thought nothing of driving across the country with no job lined up. I figured I could move into an apartment and find a job in a few weeks. What I discovered was that my lack of experience was a major problem for most companies. My previous job had been working for a small company being run by a professor. He recruited me into his company when he saw one of my projects for his class. They were tiny. We had our company meetings in coffee shops around campus. I did all of my work in my own dorm room.

It became apparent that I lacked a great deal of real-world industry programming experience. I definitely needed to be molded, and all of the companies who saw my resume seemed to realize that.

I applied for a ton of jobs, and only heard back from one. I bought a suit the day before my interview, the only suit I had owned since I bought one for a funeral when I was a teenager.

My First Interview

My first interview

The company was in Denver. I drove into the city (for the first time since I moved to Colorado) and looked for the office. The buildings seemed to skip over the address I had written. Eventually I discovered that I had to walk between two buildings, into the side entrance to the basement of one of them. No logo was on the door, so I knocked, terrified at what might open the door. A woman opened, told me I was at the right place, and invited me in. Once I stepped inside, I was asked to take my shoes off, so I didn't track dirt onto the rug. While I sat in the "waiting area" a guy came out from an adjacent room and fiddled with a cable modem plugged in behind me. The "company" consisted of 3 people, including the receptionist. Once my "interview" began, I was asked to write some code in JSP. I had explained in my cover letter that I didn't know anything about JSP, but I've used Java and I'd be happy to learn JSP. He told me to write the code anyway. "Figure it out."

I sat in front of the computer, using the internet to look up information about JSP. Having never used it before at all, I was impressed that I managed to figure out what I did. Unfortunately, the task was connecting to a database. I needed the database connection string from my interviewer, but he refused to give it to me. He told me that was part of "figuring it out". To connect to a database, I needed to know the server address, login, and password. How he expected me to figure that out, I have no idea. Needless to say, I was unable to complete the task, and I didn't get the job.

As I drove home, I was terrified. I thought I'd be able to get a job, but the only one that even called me back was a place for which I was completely unqualified. Do I not know enough about the "industry" to get a real job? How will I pay my bills while I read all the books I need? How will I afford those books? As shady as that company was, I needed the job. It sucked I didn't get it.

I stopped applying to jobs for a while. I bought three books on J2EE and tried to read through them as quickly as possible, but I found the content difficult since I lacked any kind of context. I put my job hunt on hold for a while, figuring I was unfit for the working world. About a week later, I decided to look at jobs again. I saw a job post by a company called InsightAmerica. Without a second thought, I pasted my cover letter and modified a word or two, then sent it off. I expected nothing to come of it, but the job description only mentioned Java, so maybe my lack of EE experience wouldn't be a problem.

Within an hour, the hiring manager called me. I got a quickie phone interview and I was told someone would call me later for a technical interview. Later in the day, a guy named Duke called me and asked me some questions. I tanked his SQL questions, and I remember distinctly doing terribly with his "how many barbers are there in the U.S." question. Somehow, though, I got an interview the next day.

My Second Interview

Conrad

I showed up in my suit again and interviewed with Duke, a woman named Lisa, a skinny guy named Neal, and a big guy named Conrad, who was the first person who called me.

Conrad didn't ask me anything at all. It seemed clear he had already decided that he wasn't particularly interested in me. He wouldn't even answer my questions about the company, presumably because I'd never be working there if he had his way. He spent the entire interview making jokes, clearly detached from the process and uninterested in evaluating me.

Lisa stared me down the entire interview. Every time I tried to make a joke, she knocked the wind out of my sails. She saw that I wrote "Scheme" on my resume and asked what it was. I explained it was like Lisp, and she asked how often I used it. I said I wrote some programs with it in school, and she laughed in my face, telling me if she had known you could put that on a resume she'd have put Cobol on hers. Every time I answered a question, I was met with a skeptical snarl on her face.

Neal was quiet for most of the interview. It was clear, however, that he didn't like how young I was. One of my interview questions was "If you didn't have any work to do, how would you spend your day?" I thought about it and realized that I'd probably read articles on the internet or advance a chapter in a computer book, since I like learning new languages and technologies. I responded "I guess I'd read," and Neal chimed in with "comic books?"

Duke asked me more technical questions, but I didn't do very well with them. Most of his questions were geared toward the kinds of things a professional programmer would know, centering around writing maintainable code. Since my previous job didn't need the code to be maintainable, and I was never graded in school on code elegance, this was experience I lacked, and it showed. He asked me about the software development life cycle, and I didn't even know what he meant. I was feeling my age and inexperience dragging me down.

I drove away from the company feeling like I had once again wasted my time. I didn't hear from the company after that, and I applied for a job at Best Buy. I started thinking about working at a fast food joint, or working for my old company remotely. I felt like my life was falling apart. "I'm a smart guy," I thought to myself, "I'd be great as a developer, I just need someone to look past my inexperience and take a chance on me."

My First Real Job

Cubicle

InsightAmerica took that chance. I actually got an offer from them a week after that horrendous interview. I remember thinking at the time I'd never be able to spend the money they offered me. When I showed up for work the first day, I was so excited. A real office! Real cubicles! Holy hell, I get my own cubicle!

I jumped into my project and learned as much as I could. It turned out that I was hired as Lisa's errand boy. She inherited an enormous Java application, and needed to devote herself to modifying the code, so she needed me to take over operational tasks on the system (like rebooting servers, manually fixing records in a database, etc). It was boring work, but I had access to the code. I read through it whenever I could. I learned a great deal about good OO development during that process, and I eventually got to a point where I understood the code better than Lisa. At one point, we both got an e-mail requesting a change. An hour later, an e-mail arrived from Lisa where she responded to the requestor by saying that the change would take weeks. I saw it appear in my inbox just after I hit send on my own e-mail explaining I had made the change and pushed it out to the server.

As time went on, Lisa was taken off the project and I was made lead developer on it. I learned more and more about what it means to develop code professionally, and eventually became well-regarded by the rest of the team. I actually learned enough to be regarded as something of an "expert" on OO development. Along with Duke, I became the "Java Guy" at the company, answering questions other developers had. I even led a few presentations on various computer science concepts. Within a year or so, I was conducting technical interviews and I had the word "senior" attached to my title. A 23-year-old with "senior" in his title.

During my time at the company, Conrad and Lisa were both fired. Neal became the manager. Duke became one of my best friends. Neal told me one day that Conrad and Lisa were both adamant I not be hired because I was so young, but he and Duke both wanted to take a chance on me, figuring I would turn out to be one of their best employees. Neal explained that he was right, and it was one of the nicest complements I'd ever received.

Moving On

InsightAmerica was my first real job in an office. It's hard to believe I've only been working here two years, since I feel like I've learned so much. I'm Sun-Certified in Java, highly knowledgeable about OO and Design Patterns, and almost finished with a Masters program. I also have a Sun Certification in JSPs and Servlets, so fuck you, basement-company. I'm a much better developer than I was two years ago, and nothing illustrated that to me better than my recent job search.

It was difficult to decide to leave my company, since I was so grateful for the experience. However, I had to be realistic, and it was definitely time to move on. Even Neal left the company.

My new company is smaller, and they do really interesting work. They deal with open source software, one of my passions. Everything about the job is perfect (including a salary bump). It's a team of really bright geek types doing work that can make them proud.

I'm extremely excited about my new job, and I can't wait to start. It is tough, however, to leave the first company that took a chance on me. The first company to teach me what it meant to write truly maintainable code. The first company to mold my understanding of Computer Science into something applicable to the software industry. The first company to encourage me to learn new languages and technologies, allowing me to finally feel worthy of employment at a real company. InsightAmerica taught me what I needed to know to get a job better than the one at InsightAmerica.

People have told me during my two years that I've taught them a lot about Java, OO, and Computer Science.

The truth is, it was I who learned the most from the experience.

Using Western Digital NetCenter with Ubuntu Linux

I bought a Western Digital NetCenter drive in anticipation of switching to Linux not too long ago (wanted a place for multimedia). While Windows had no problem using the shares I set up on the drive, getting it to work in Linux has been a nightmare. After a lot of failed discussions in #ubuntu on the IRC Server, as well as a post on the Ubuntu Forum that went unanswered for a month, I figured out the problems and decided to post my own tutorial so that poor schmoes like me searching for NetCenter-specific information could find it.

Before I go through this, you'll need to see if my goal with the NetCenter is close to your own. Basically, I wanted a place for multimedia on the network, such as mp3s and the like. I wanted to be able to still download stuff using my Linux machine (my main Desktop computer), but then move stuff to the network drive. This meant that I wanted a simple directory somewhere within Linux that behaved as though I had all of my multimedia on the machine itself. In Windows, I'd map my MP3 Share to the Z: drive, so my mp3s were always at Z:\. I wanted it to be similarly simple in Linux.

Preparing the Shares

Step one is to enable NFS on your shares. When you make a share in the NetCenter web admin tool, you must make sure that, for the security settings for your folder, you enable NFS.

I believe the NetCenter comes with some kind of Windows-centric application to manage shares, but I didn't bother with that. Once you find out your NetCenter's ip address, you can simply load that IP in your web browser and find the web admin tool. Make your shares through that.

I'm going to assume you have made a share called MUSIC, and you intend to place all of your mp3s there. I'm also going to assume you are making it a PUBLIC share, rather than password-protected. I'm assuming this because that's what I did, and thus I have no idea how to work with the password-protected shares. I can only assume it's about as painless as simple as working with public shares, which is to say I imagine you're going to want to pull your eyeballs out and eat them if you attempt such a thing.

Mounting in Linux

Almost all of the other tutorials on the web that discuss this kind of thing have you mount your shares using SMBFS. This is an awful idea, because SMBFS apparently has some bug in it. The end-result of this bug is that, if two threads try to access the mount concurrently, the entire mount will freeze, any application reading from it will freeze, and any program that tries to access it again will freeze. This will last a few hours (3 for me) before the share is magically available again. Oh, and if you have other mounts going to the same machine, those will freeze too.

This is particularly frustrating when you are storing MP3 files, because when you scan your library most programs will do so in a threaded manner, thus instantly breaking everything for a good 3 hours or so.

The workaround for this, I found, is to avoid SMBFS entirely and use NFS instead.

First, you need to make a directory for what you will mount to. A lot of people mount this kind of stuff inside /media, so I'll assume you want to as well (I didn't, but whatever).

Type sudo mkdir /media/mp3. This will make an mp3 directory that you will map your MUSIC share to. Now, let's mount it. Let's assume the IP address of your NetCenter drive is 192.168.0.200.

Type sudo mount -t nfs 192.168.0.200:/shares/Main/MUSIC /media/mp3

That should be it. Cd into /media/mp3 and list some files. To unmount it, type sudo umount /media/mp3.

If you wanted to mount with cifs instead, the path would simply be //IP/MUSIC, so you might be wondering what the /shares/Main is for. The Western Digital runs a flavor of linux itself, which is why using NFS is so much better. However, it hides the location of your shares in /shares/volume_name/share_name. This isn't found anywhere in any documentation, and if you send Western Digital an e-mail simply asking "I'm trying to mount using NFS, what's the path to my share on the drive?" they will respond by telling you they do not support Linux. If you respond and tell them you aren't asking about Linux, you are asking about NFS, which the drive clearly supports as there is a checkbox for enabling it for every share you make, they will reply again by telling you they do not support Linux.

Western Digital loses major points with me for how they have handled this situation. It's frustrating enough that they don't support Linux on a network-attached storage device (since the most common use of NAS is enterprise, and a lot of companies run on Linux). but to refuse to help with an actual feature of their device was particularly infuriating. If support is important to you, do NOT buy a Western Digital NetCenter drive. The drive works great once you get it working correctly, but WD will not help you.

Automounting

To make it so that this is mounted when you boot your machine, type sudo gedit /etc/fstab

Then add this line to your file:

192.168.0.200:/shares/Main/MUSIC   /media/mp3  nfs  rw,user  0       0

Save the file, and do sudo mount -a in a terminal. This should reload the file and mount whatever is there. This will occur automatically when you boot from now on.

You will also notice that an icon appears on your desktop for this drive. I found this bothersome, and if you do as well, simply remove the ",user" from the config line.

Writing to the directory

You may find as you try to move files into the share, that you cannot write. In my case, I moved a lot of files onto the drive from Windows before switching to Linux, so all of my music and multimedia was already on the drive. I discovered I couldn't read any of it or move additional files to existing directories.

The following steps will 1) Make all of the directories writable for EVERYONE on the network 2) Make all of the files readable and writable for everyone on the network and 3) Change the owner of everything on the drive to "root".

This is an extremely permissive way to set up your network share. The reason I provide instructions like this is that, when the WD NetCenter is set to "public", the behavior of the drive is that everyone in windows can read and write to everything on that share. Thus, I am trying to emulate that behavior in Linux. If you want to use a more restrictive permissions scheme, you can go ahead. Feel free to add to these instructions in the comments if that is the case for you.

In any case, the first thing you need to do is set all of the directories on the drive to be read/write/execute for everyone. Type this: sudo chmod -R a+rwX /media/mp3

This will set +rw for everyone, and set the X bit for everyone if it's already set for the user (since directories have this bit set to allow directory listing, the end-effect is that directories will be set correctly). This also sets all files to be +rw, but not +x.

The next thing to do is change the owner. This is mostly for cosmetic purposes: sudo chown -R root:root /media/mp3.

That's it. Your drive should now be usable by you without having to sudo.

My Interview With Google

Update: Apparently this site (talking about the ways in which people blew their Google interviews) links to me, and also used my picture. It kind of sucks that an article titled "How I Blew My Google Interview" has my face on it, but that's what happens when you put a picture on the internet, I guess. More disconcerting to me is that the portion of the article below that was highlighted was my discussion of my interview with the guy with the thick accent. The implication of the linked article is that I blew the interview by not understanding him. I'd like to clarify, that part of the experience was just a relevant part of the story, which is why I shared it. I blew the Google Interview not for that reason, but because my algorithm skills simply were not up to snuff at the time. Blaming the rejection on having a hard time with accents would be petty and silly. I was rejected because I wasn't good enough, plain and simple.

Recently, I had the pleasure of interviewing with Google. It was very exciting, as I've wanted to work for Google for quite some time, and they opened up a branch near my home through an acquisition recently. I wanted to share the process of interviewing with Google, not because it was particularly noteworthy, but because I wondered about interviewing with Google before I did so, and I figured others might. I've had to sign an NDA, so I'm going to be pretty careful about what I share in this post.

Me, excited

The position I interviewed for was a Software Engineer position in the Boulder, Colorado office (near where I live), but they still conduct their interviews from the California office. Because I'm not in California, I had to go through two phone interviews first. The questions Google asks are pretty interesting for a number of reasons. I think the best word I could use to describe the questions is "fair". I didn't get any tricky puzzle questions. Nobody asked me what I would do if I were shrunk to the size of a nickel and thrown in a blender. Not a single question was an "a-ha!" type brain-teaser. Pretty much every question was a good question for figuring out if someone can write code. Even though I was interviewing for a Java position, I only had one Java-specific question. I could really feel from the questions that Google wasn't concerned with me being good with a specific language; they really wanted to know if I was just a good coder.

When I was first told by the recruiter that the questions would be algorithm-based, I was worried I'd have to reproduce quicksort or something. In fact, the questions were far, far more reasonable (though reviewing sorting algorithms WAS a good idea). Most of them involved manipulating data in an array for some purpose. I'd give an answer that worked, and they'd ask me if there were any corner cases. I was asked to solve the problem in a way that avoided those problems. Then I was asked to improve the space efficiency or running efficiency of the solution. A solution that "worked" was never enough, the interviewers always pushed me further, trying to squeeze out performance. I had to say the runtime complexity for nearly every solution I suggested. I would NOT recommend interviewing with Google without a Computer Science degree. You need to be able to look at a function and know the Big-O for it immediately. Specifically, you need to look at YOUR OWN functions and know the Big-O immediately.

Me, humming the Full House theme in my head

After doing well with both of these interviews, Google actually flew me out to California for a weekend for an all-day interview on the Google campus. They paid for my plane ticket, hotel room, rental car, and some food. I bought a second ticket for my fiancee and we did touristy crap around San Francisco. Overall, it was a lot of fun, but I couldn't help but keep the back of my head occupied with the thought of an all-day interview.

On Monday, I went to the Google campus. In the main lobby, they have a projector with a scrolling list of Google searches. I sat in the lobby waiting for my interview to begin, happily watching the searches scroll by. Lots of female celebrities were being searched, and someone searched for "vista crack" which made me laugh out loud, ensuring the receptionist thought I was an idiot. I sent my fiancee a text message telling her to search for "Rod is awesome" but it didn't show up. They also had a neat visualization showing where people were doing searches on a spinning globe.

Pictures of Googlers with celebrities adorned the wall next to the new Google whiteboard. For those that don't know, Google has a giant whiteboard which was finally erased not too long ago. Before being erased, someone took pictures and posted them to the internet. The new board was already mostly full by the time I saw it, and a large section of it was devoted to complaining about the board being erased.

Some random Google building

I also had lunch in one of the cafes on campus. The Google cafes are all buffet-style, and completely free. You simply walk in, grab whatever the hell you want, and leave. My "lunch-date" was one of my phone interviewers, and he took me to the health food cafe. Salads, tofu, bean sprouts, and similar food items filled the buffet. I searched desperately for some meat and filled my plate when I finally found it. I'm definitely NOT a California person. People looked at me like I personally killed a cow in front of them.

The on-site interviews were much like the phone interviews. I had one-on-one meetings with a handful of people, one after another. Each person asked me algorithm-type questions. I did some whiteboarding, but was mostly able to write the answers in my notebook, which was better for me as I could keep up with my brain much more easily on paper than on a whiteboard. It was sometimes difficult to focus on the questions while "OH MY GOD I'M INTERVIEWING WITH FUCKING GOOGLE" whizzed by in my brain over and over. Luckily, pretty much everyone was extremely friendly, which helped calm my considerable nerves.

The biggest difference in the questions between phone and on-site interviews was how my answers had to be presented. On the phone, it was sufficient that I explain, at a high-level, how the solution to a problem would work. On-site, I had to actually write it out. Of my four interviewers, two actually wanted it to be valid Java.

I finished early with one of my interviewers, and he asked me a joke question: if a Stormtrooper shoots a red-shirt, does he hit? It was comical how universal this seemed. Of course I'd know what he was talking about, I write software. Luckily, I was familiar with the term redshirt from being a film nerd, and I was able to come up with a joke answer that didn't let him on to the fact I've never seen a single episode of Star Trek in my life.

Part of the Google Campus

The worst part of the process was my fourth and final interview of the day. The guy was from Moscow, and he had a very thick accent. All of my life, I've had immense trouble with accents, even slight ones. My project manager at work has a thick accent from Italy, and she basically sounds like Chewbacca to me. I'm not complaining that Moscow Guy had an accent (all tech companies have folks with accents), but it sure made the rest of the interview process challenging for me. My interview with the Moscow Guy resembled one of those satellite interviews on the news. He'd say something to me, and there'd be this long pause before I responded. To make matters worse, he told me his first question was going to be "an easy one", so when I barely understood what he said at all, I imagine I looked like a complete imbecile. "What was that? You want me to WHAT two numbers together? Mo de ploy? Mah dah bu? Oh, multiply! Right, two times two is four. I'm obviously partially retarded."

To make matters worse, the Moscow guy was the only person I talked to the entire day who wasn't friendly. He wasn't a complete jerk or anything, but he definitely wasn't as warm as my other interviewers. Right before the interview ended, he asked me what I'd work on for my "20% time" project. Each Google employee gets to devote 20% of their time to a side project, which is why so many of the Google Labs projects exist (like Gmail and Movie Search). I actually had an answer to this question, since I thought about it on the plane ride out to California. There's been a side project I've been wanting to work on at home, but I haven't had time. I figured, if I got the job, I'd just make that a Google Labs project and do it there. I explained my idea to him, and he told me it sounded interesting, then proceeded to write it down right in front of me. All I could think was "I hope I get this job so I don't regret that."

I imagine the four interview feedback e-mails looked like this:

  1. "Candidate knew his stuff, but seemed awfully nervous."
  2. "Candidate knew his stuff and seemed relatively comfortable."
  3. "Candidate kept joking around like I was his friend. Clearly was not nervous enough, given that he was interviewing at FUCKING GOOGLE."
  4. "Candidate seemed to have the brain of a chimp. Was surprised he could speak without forgetting to breathe. Interviewer confident candidate eats glue."

Google Lobby

I flew back to Colorado feeling pretty good about the whole thing. As it turns out, though, I was told over the phone (while trying to push a car out of the snow during the Denver blizzard) that I didn't get the position. I need to work on my algorithm skills, so I guess I got docked for not thinking of the best solution right away. The Google Recruiter told me it wasn't the last guy that did me in, but I imagine if I had tried to come up with the best solution earlier (rather than the naive one so I could improve it) and if I had gotten a different interviewer for my last interview, I'd be writing this blog post from my desk at Google.

Considering how much I wanted the job, I admit I'm pretty bummed about this. I'm allowed to re-apply in a year, but I can't imagine improving my "algorithm skills" without more information on where my problem areas were. What's really unfortunate is that I know if Google had hired me, I'd have done a good job. If I see my idea appear on Google Labs any time soon, I'm going to go nuts.

All in all, it was a pretty pleasant experience. I'm disappointed, but I'm proud of myself for at least being considered seriously by Google. It was honestly kind of fun answering their interview questions. The questions reminded me of my undergraduate work, and it was nice to think about that kind of material again. I'm bummed that my progress into the world of Google came to such a screeching halt, but the journey has definitely been fun and interesting. And hey, I got a free trip to San Francisco out of it.